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

1.1       root        1: /* Subroutines for assembler code output on the NS32000.
                      2:    Copyright (C) 1988 Free Software Foundation, Inc.
                      3: 
                      4: This file is part of GNU CC.
                      5: 
                      6: GNU CC is free software; you can redistribute it and/or modify
                      7: it under the terms of the GNU General Public License as published by
                      8: the Free Software Foundation; either version 2, or (at your option)
                      9: any later version.
                     10: 
                     11: GNU CC is distributed in the hope that it will be useful,
                     12: but WITHOUT ANY WARRANTY; without even the implied warranty of
                     13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     14: GNU General Public License for more details.
                     15: 
                     16: You should have received a copy of the GNU General Public License
                     17: along with GNU CC; see the file COPYING.  If not, write to
                     18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
                     19: 
                     20: /* 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: {
1.1.1.3 ! root       41:   fprintf (stderr, s, s1, s2);
1.1       root       42: }
                     43: 
                     44: /* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. */ 
                     45: 
                     46: int
1.1.1.3 ! root       47: hard_regno_mode_ok (regno, mode)
        !            48:      int regno;
        !            49:      int 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;
1.1       root       86:        }
1.1.1.3 ! root       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:   abort(0);
1.1       root      111: }
                    112: 
                    113: /* ADDRESS_COST calls this.  This function is not optimal
                    114:    for the 32032 & 32332, but it probably is better than
                    115:    the default. */
                    116: 
                    117: int
                    118: calc_address_cost (operand)
                    119:      rtx operand;
                    120: {
                    121:   int i;
                    122:   int cost = 0;
                    123:   
                    124:   if (GET_CODE (operand) == MEM)
                    125:     cost += 3;
                    126:   if (GET_CODE (operand) == MULT)
                    127:     cost += 2;
                    128: #if 0
                    129:   if (GET_CODE (operand) == REG)
                    130:     cost += 1;                 /* not really, but the documentation
                    131:                                   says different amount of registers
                    132:                                   shouldn't return the same costs */
                    133: #endif
                    134:   switch (GET_CODE (operand))
                    135:     {
                    136:     case REG:
                    137:     case CONST:
                    138:     case CONST_INT:
                    139:     case CONST_DOUBLE:
                    140:     case SYMBOL_REF:
                    141:     case LABEL_REF:
                    142:     case POST_DEC:
                    143:     case PRE_DEC:
                    144:       break;
                    145:     case MULT:
                    146:     case MEM:
                    147:     case PLUS:
                    148:       for (i = 0; i < GET_RTX_LENGTH (GET_CODE (operand)); i++)
                    149:        {
                    150:          cost += calc_address_cost (XEXP (operand, i));
                    151:        }
                    152:     default:
                    153:       break;
                    154:     }
                    155:   return cost;
                    156: }
                    157: 
                    158: /* Return the register class of a scratch register needed to copy IN into
                    159:    or out of a register in CLASS in MODE.  If it can be done directly,
                    160:    NO_REGS is returned.  */
                    161: 
                    162: enum reg_class
                    163: secondary_reload_class (class, mode, in)
                    164:      enum reg_class class;
                    165:      enum machine_mode mode;
                    166:      rtx in;
                    167: {
                    168:   int regno = true_regnum (in);
                    169: 
                    170:   if (regno >= FIRST_PSEUDO_REGISTER)
                    171:     regno = -1;
                    172: 
                    173:   /* We can place anything into GENERAL_REGS and can put GENERAL_REGS
                    174:      into anything.  */
                    175:   if (class == GENERAL_REGS || (regno >= 0 && regno < 8))
                    176:     return NO_REGS;
                    177: 
1.1.1.3 ! root      178:   /* Constants, memory, and FP registers can go into FP registers.  */
1.1       root      179:   if ((regno == -1 || (regno >= 8 && regno < 16)) && (class == FLOAT_REGS))
                    180:     return NO_REGS;
                    181: 
1.1.1.3 ! root      182: #if 0 /* This isn't strictly true (can't move fp to sp or vice versa),
        !           183:         so it's cleaner to use PREFERRED_RELOAD_CLASS
        !           184:         to make the right things happen.  */
        !           185:   if (regno >= 16 && class == GEN_AND_MEM_REGS)
        !           186:     return NO_REGS;
        !           187: #endif
        !           188: 
1.1       root      189:   /* Otherwise, we need GENERAL_REGS. */
                    190:   return GENERAL_REGS;
                    191: }
                    192: /* Generate the rtx that comes from an address expression in the md file */
                    193: /* The expression to be build is BASE[INDEX:SCALE].  To recognize this,
                    194:    scale must be converted from an exponent (from ASHIFT) to a
1.1.1.2   root      195:    multiplier (for MULT). */
1.1       root      196: rtx
                    197: gen_indexed_expr (base, index, scale)
                    198:      rtx base, index, scale;
                    199: {
                    200:   rtx addr;
                    201: 
                    202:   /* This generates an illegal addressing mode, if BASE is
                    203:      fp or sp.  This is handled by PRINT_OPERAND_ADDRESS.  */
                    204:   if (GET_CODE (base) != REG && GET_CODE (base) != CONST_INT)
                    205:     base = gen_rtx (MEM, SImode, base);
                    206:   addr = gen_rtx (MULT, SImode, index,
                    207:                  gen_rtx (CONST_INT, VOIDmode, 1 << INTVAL (scale)));
                    208:   addr = gen_rtx (PLUS, SImode, base, addr);
                    209:   return addr;
                    210: }
                    211: 
                    212: /* Return 1 if OP is a valid operand of mode MODE.  This
                    213:    predicate rejects operands which do not have a mode
                    214:    (such as CONST_INT which are VOIDmode).  */
                    215: int
                    216: reg_or_mem_operand (op, mode)
                    217:      register rtx op;
                    218:      enum machine_mode mode;
                    219: {
                    220:   return (GET_MODE (op) == mode
                    221:          && (GET_CODE (op) == REG
                    222:              || GET_CODE (op) == SUBREG
                    223:              || GET_CODE (op) == MEM));
                    224: }
                    225: 
                    226: /* Return the best assembler insn template
                    227:    for moving operands[1] into operands[0] as a fullword.  */
                    228: 
                    229: static char *
                    230: singlemove_string (operands)
                    231:      rtx *operands;
                    232: {
                    233:   if (GET_CODE (operands[1]) == CONST_INT
                    234:       && INTVAL (operands[1]) <= 7
                    235:       && INTVAL (operands[1]) >= -8)
                    236:     return "movqd %1,%0";
                    237:   return "movd %1,%0";
                    238: }
                    239: 
                    240: char *
                    241: output_move_double (operands)
                    242:      rtx *operands;
                    243: {
                    244:   enum anon1 { REGOP, OFFSOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
                    245:   rtx latehalf[2];
                    246: 
                    247:   /* First classify both operands.  */
                    248: 
                    249:   if (REG_P (operands[0]))
                    250:     optype0 = REGOP;
                    251:   else if (offsettable_memref_p (operands[0]))
                    252:     optype0 = OFFSOP;
                    253:   else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
                    254:     optype0 = POPOP;
                    255:   else
                    256:     optype0 = RNDOP;
                    257: 
                    258:   if (REG_P (operands[1]))
                    259:     optype1 = REGOP;
                    260:   else if (CONSTANT_ADDRESS_P (operands[1])
                    261:           || GET_CODE (operands[1]) == CONST_DOUBLE)
                    262:     optype1 = CNSTOP;
                    263:   else if (offsettable_memref_p (operands[1]))
                    264:     optype1 = OFFSOP;
                    265:   else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
                    266:     optype1 = POPOP;
                    267:   else
                    268:     optype1 = RNDOP;
                    269: 
                    270:   /* Check for the cases that the operand constraints are not
                    271:      supposed to allow to happen.  Abort if we get one,
                    272:      because generating code for these cases is painful.  */
                    273: 
                    274:   if (optype0 == RNDOP || optype1 == RNDOP)
                    275:     abort ();
                    276: 
                    277:   /* Ok, we can do one word at a time.
                    278:      Normally we do the low-numbered word first,
                    279:      but if either operand is autodecrementing then we
                    280:      do the high-numbered word first.
                    281: 
                    282:      In either case, set up in LATEHALF the operands to use
                    283:      for the high-numbered word and in some cases alter the
                    284:      operands in OPERANDS to be suitable for the low-numbered word.  */
                    285: 
                    286:   if (optype0 == REGOP)
                    287:     latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
                    288:   else if (optype0 == OFFSOP)
                    289:     latehalf[0] = adj_offsettable_operand (operands[0], 4);
                    290:   else
                    291:     latehalf[0] = operands[0];
                    292: 
                    293:   if (optype1 == REGOP)
                    294:     latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
                    295:   else if (optype1 == OFFSOP)
                    296:     latehalf[1] = adj_offsettable_operand (operands[1], 4);
                    297:   else if (optype1 == CNSTOP)
                    298:     {
                    299:       if (CONSTANT_ADDRESS_P (operands[1]))
                    300:        latehalf[1] = const0_rtx;
                    301:       else if (GET_CODE (operands[1]) == CONST_DOUBLE)
                    302:        split_double (operands[1], &operands[1], &latehalf[1]);
                    303:     }
                    304:   else
                    305:     latehalf[1] = operands[1];
                    306: 
                    307:   /* If one or both operands autodecrementing,
                    308:      do the two words, high-numbered first.  */
                    309: 
                    310:   if (optype0 == POPOP || optype1 == POPOP)
                    311:     {
                    312:       output_asm_insn (singlemove_string (latehalf), latehalf);
                    313:       return singlemove_string (operands);
                    314:     }
                    315: 
                    316:   /* Not autodecrementing.  Do the two words, low-numbered first.  */
                    317: 
                    318:   output_asm_insn (singlemove_string (operands), operands);
                    319: 
                    320:   operands[0] = latehalf[0];
                    321:   operands[1] = latehalf[1];
                    322:   return singlemove_string (operands);
                    323: }
                    324: 
                    325: int
                    326: check_reg (oper, reg)
                    327:      rtx oper;
                    328:      int reg;
                    329: {
                    330:   register int i;
                    331: 
                    332:   if (oper == 0)
                    333:     return 0;
                    334:   switch (GET_CODE(oper))
                    335:     {
                    336:     case REG:
                    337:       return (REGNO(oper) == reg) ? 1 : 0;
                    338:     case MEM:
                    339:       return check_reg(XEXP(oper, 0), reg);
                    340:     case PLUS:
                    341:     case MULT:
                    342:       return check_reg(XEXP(oper, 0), reg) || check_reg(XEXP(oper, 1), reg);
                    343:     }
                    344:   return 0;
                    345: }
                    346: 
                    347: /* PRINT_OPERAND is defined to call this function,
                    348:    which is easier to debug than putting all the code in
                    349:    a macro definition in ns32k.h.  */
                    350: 
                    351: void
                    352: print_operand (file, x, code)
                    353:      FILE *file;
                    354:      rtx x;
                    355:      char code;
                    356: {
                    357:   if (code == '$')
1.1.1.3 ! root      358:     PUT_IMMEDIATE_PREFIX (file);
1.1       root      359:   else if (code == '?')
1.1.1.3 ! root      360:     PUT_EXTERNAL_PREFIX (file);
1.1       root      361:   else if (GET_CODE (x) == REG)
                    362:     fprintf (file, "%s", reg_names[REGNO (x)]);
                    363:   else if (GET_CODE (x) == MEM)
1.1.1.2   root      364:     {
                    365:       rtx tmp = XEXP (x, 0);
1.1.1.3 ! root      366: #if ! (defined (PC_RELATIVE) || defined (NO_ABSOLUTE_PREFIX_IF_SYMBOLIC))
        !           367:       if (GET_CODE (tmp) != CONST_INT)
1.1.1.2   root      368:        {
                    369:          char *out = XSTR (tmp, 0);
                    370:          if (out[0] == '*')
1.1.1.3 ! root      371:            {
        !           372:              PUT_ABSOLUTE_PREFIX (file);
        !           373:              fprintf (file, "%s", &out[1]);
        !           374:            }
1.1.1.2   root      375:          else
                    376:            ASM_OUTPUT_LABELREF (file, out);
                    377:        }
                    378:       else
                    379: #endif
                    380:        output_address (XEXP (x, 0));
                    381:     }
1.1       root      382:   else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) != DImode)
1.1.1.2   root      383:     {
                    384:       if (GET_MODE (x) == DFmode)
                    385:        { 
                    386:          union { double d; int i[2]; } u;
                    387:          u.i[0] = CONST_DOUBLE_LOW (x); u.i[1] = CONST_DOUBLE_HIGH (x);
                    388:          PUT_IMMEDIATE_PREFIX(file);
                    389: #ifdef SEQUENT_ASM
                    390:          /* Sequent likes it's floating point constants as integers */
1.1.1.3 ! root      391:          fprintf (file, "0Dx%08x%08x", u.i[1], u.i[0]);
1.1.1.2   root      392: #else
                    393: #ifdef ENCORE_ASM
                    394:          fprintf (file, "0f%.20e", u.d); 
                    395: #else
                    396:          fprintf (file, "0d%.20e", u.d); 
                    397: #endif
                    398: #endif
                    399:        }
                    400:       else
                    401:        { 
                    402:          union { double d; int i[2]; } u;
                    403:          u.i[0] = CONST_DOUBLE_LOW (x); u.i[1] = CONST_DOUBLE_HIGH (x);
1.1.1.3 ! root      404:          PUT_IMMEDIATE_PREFIX (file);
1.1.1.2   root      405: #ifdef SEQUENT_ASM
1.1.1.3 ! root      406:          /* We have no way of winning if we can't get the bits
        !           407:             for a sequent floating point number.  */
        !           408: #if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
        !           409:          abort ();
        !           410: #endif
1.1.1.2   root      411:          {
                    412:            union { float f; long l; } uu;
                    413:            uu.f = u.d;
                    414:            fprintf (file, "0Fx%08x", uu.l);
                    415:          }
                    416: #else
                    417:          fprintf (file, "0f%.20e", u.d); 
                    418: #endif
                    419:        }
                    420:     }
1.1       root      421:   else
                    422:     {
1.1.1.3 ! root      423: #ifndef NO_IMMEDIATE_PREFIX_IF_SYMBOLIC
        !           424:       if (GET_CODE (x) == CONST_INT)
        !           425: #endif
        !           426:        PUT_IMMEDIATE_PREFIX(file);
1.1       root      427:       output_addr_const (file, x);
                    428:     }
                    429: }
                    430: 
                    431: /* PRINT_OPERAND_ADDRESS is defined to call this function,
                    432:    which is easier to debug than putting all the code in
                    433:    a macro definition in ns32k.h .  */
                    434: 
                    435: /* Completely rewritten to get this to work with Gas for PC532 Mach.
                    436:    This function didn't work and I just wasn't able (nor very willing) to
                    437:    figure out how it worked.
                    438:    90-11-25 Tatu Yl|nen <[email protected]> */
                    439: 
                    440: print_operand_address (file, addr)
                    441:      register FILE *file;
                    442:      register rtx addr;
                    443: {
                    444:   static char scales[] = { 'b', 'w', 'd', 0, 'q', };
                    445:   rtx offset, base, indexexp, tmp;
                    446:   int scale;
                    447: 
                    448:   if (GET_CODE (addr) == PRE_DEC || GET_CODE (addr) == POST_DEC)
                    449:     {
                    450:       fprintf (file, "tos");
                    451:       return;
                    452:     }
                    453: 
                    454:   offset = NULL;
                    455:   base = NULL;
                    456:   indexexp = NULL;
                    457:   while (addr != NULL)
                    458:     {
                    459:       if (GET_CODE (addr) == PLUS)
                    460:        {
                    461:          if (GET_CODE (XEXP (addr, 0)) == PLUS)
                    462:            {
                    463:              tmp = XEXP (addr, 1);
                    464:              addr = XEXP (addr, 0);
                    465:            }
                    466:          else
                    467:            {
                    468:              tmp = XEXP (addr,0);
                    469:              addr = XEXP (addr,1);
                    470:            }
                    471:        }
                    472:       else
                    473:        {
                    474:          tmp = addr;
                    475:          addr = NULL;
                    476:        }
                    477:       switch (GET_CODE (tmp))
                    478:        {
                    479:        case PLUS:
                    480:          abort ();
                    481:        case MEM:
                    482:          if (base)
                    483:            {
                    484:              indexexp = base;
                    485:              base = tmp;
                    486:            }
                    487:          else
                    488:            base = tmp;
                    489:          break;
                    490:        case REG:
                    491:          if (REGNO (tmp) < 8)
                    492:            if (base)
                    493:              {
                    494:                indexexp = tmp;
                    495:              }
                    496:            else
                    497:              base = tmp;
                    498:          else
                    499:            if (base)
                    500:              {
                    501:                indexexp = base;
                    502:                base = tmp;
                    503:              }
                    504:            else
                    505:              base = tmp;
                    506:          break;
                    507:        case MULT:
                    508:          indexexp = tmp;
                    509:          break;
                    510:        case CONST:
                    511:        case CONST_INT:
                    512:        case SYMBOL_REF:
                    513:        case LABEL_REF:
                    514:          if (offset)
                    515:            offset = gen_rtx (PLUS, SImode, tmp, offset);
                    516:          else
                    517:            offset = tmp;
                    518:          break;
                    519:        default:
                    520:          abort ();
                    521:        }
                    522:     }
                    523:   if (! offset)
                    524:     offset = const0_rtx;
1.1.1.3 ! root      525: 
        !           526: #ifdef INDEX_RATHER_THAN_BASE
        !           527:   /* This is a re-implementation of the SEQUENT_ADDRESS_BUG fix.  */
        !           528:   if (base && !indexexp && GET_CODE (base) == REG
        !           529:       && REG_OK_FOR_INDEX_P (REGNO (base))
        !           530:     {
        !           531:       indexexp = base;
        !           532:       base = 0;
        !           533:     }
        !           534: #endif
        !           535: 
1.1       root      536:   /* now, offset, base and indexexp are set */
                    537:   if (! base)
                    538:     {
1.1.1.2   root      539: #if defined (PC_RELATIVE) || defined (NO_ABSOLUTE_PREFIX_IF_SYMBOLIC)
1.1.1.3 ! root      540:       if (GET_CODE (offset) == CONST_INT)
        !           541: /*      if (! (GET_CODE (offset) == LABEL_REF
        !           542:             || GET_CODE (offset) == SYMBOL_REF)) */
1.1       root      543: #endif
                    544:        PUT_ABSOLUTE_PREFIX (file);
                    545:     }
                    546: 
1.1.1.2   root      547:   output_addr_const (file, offset);
1.1       root      548:   if (base) /* base can be (REG ...) or (MEM ...) */
                    549:     switch (GET_CODE (base))
                    550:       {
                    551:        /* now we must output base.  Possible alternatives are:
                    552:           (rN)       (REG ...)
1.1.1.3 ! root      553:           (sp)       (REG ...)
1.1       root      554:           (fp)       (REG ...)
                    555:           (pc)       (REG ...)  used for SYMBOL_REF and LABEL_REF, output
                    556:           (disp(fp)) (MEM ...)       just before possible [rX:y]
                    557:           (disp(sp)) (MEM ...)
                    558:           (disp(sb)) (MEM ...)
                    559:           */
                    560:       case REG:
                    561:        fprintf (file, "(%s)", reg_names[REGNO (base)]);
                    562:        break;
                    563:       case MEM:
                    564:        addr = XEXP(base,0);
                    565:        base = NULL;
                    566:        offset = NULL;
                    567:        while (addr != NULL)
                    568:          {
                    569:            if (GET_CODE (addr) == PLUS)
                    570:              {
                    571:                if (GET_CODE (XEXP (addr, 0)) == PLUS)
                    572:                  {
                    573:                    tmp = XEXP (addr, 1);
                    574:                    addr = XEXP (addr, 0);
                    575:                  }
                    576:                else
                    577:                  {
                    578:                    tmp = XEXP (addr, 0);
                    579:                    addr = XEXP (addr, 1);
                    580:                  }
                    581:              }
                    582:            else
                    583:              {
                    584:                tmp = addr;
                    585:                addr = NULL;
                    586:              }
                    587:            switch (GET_CODE (tmp))
                    588:              {
                    589:              case REG:
                    590:                base = tmp;
                    591:                break;
                    592:              case CONST:
                    593:              case CONST_INT:
                    594:              case SYMBOL_REF:
                    595:              case LABEL_REF:
                    596:                if (offset)
                    597:                  offset = gen_rtx (PLUS, SImode, tmp, offset);
                    598:                else
                    599:                  offset = tmp;
                    600:                break;
                    601:              default:
                    602:                abort ();
                    603:              }
                    604:          }
                    605:        if (! offset)
                    606:          offset = const0_rtx;
                    607:        fprintf (file, "(");
                    608:        output_addr_const (file, offset);
                    609:        if (base)
                    610:          fprintf (file, "(%s)", reg_names[REGNO (base)]);
1.1.1.2   root      611: #ifdef BASE_REG_NEEDED
1.1       root      612:        else if (TARGET_SB)
                    613:          fprintf (file, "(sb)");
                    614:        else
                    615:          abort ();
1.1.1.2   root      616: #endif
1.1       root      617:        fprintf (file, ")");
                    618:        break;
                    619: 
                    620:       default:
                    621:        abort ();
                    622:       }
                    623: #ifdef PC_RELATIVE
                    624:   else                         /* no base */
                    625:     if (GET_CODE (offset) == LABEL_REF || GET_CODE (offset) == SYMBOL_REF)
                    626:       fprintf (file, "(pc)");
                    627: #endif
                    628: #ifdef BASE_REG_NEEDED         /* this is defined if the assembler always
                    629:                                   needs a base register */
                    630:     else if (TARGET_SB)
                    631:       fprintf (file, "(sb)");
                    632:     else
                    633:       abort ();
                    634: #endif
                    635:   /* now print index if we have one */
                    636:   if (indexexp)
                    637:     {
                    638:       if (GET_CODE (indexexp) == MULT)
                    639:        {
                    640:          scale = INTVAL (XEXP (indexexp, 1)) >> 1;
                    641:          indexexp = XEXP (indexexp, 0);
                    642:        }
                    643:       else
                    644:        scale = 0;
                    645:       if (GET_CODE (indexexp) != REG || REGNO (indexexp) >= 8)
                    646:        abort ();
                    647: 
1.1.1.3 ! root      648: #ifdef UTEK_ASM
        !           649:       fprintf (file, "[%c`%s]",
        !           650:               scales[scale],
        !           651:               reg_names[REGNO (indexexp)]);
        !           652: #else
1.1       root      653:       fprintf (file, "[%s:%c]",
                    654:               reg_names[REGNO (indexexp)],
                    655:               scales[scale]);
1.1.1.3 ! root      656: #endif
1.1       root      657:     }
                    658: }
                    659: 
                    660: /* National 32032 shifting is so bad that we can get
                    661:    better performance in many common cases by using other
                    662:    techniques.  */
                    663: char *
                    664: output_shift_insn (operands)
                    665:      rtx *operands;
                    666: {
                    667:   if (GET_CODE (operands[2]) == CONST_INT
                    668:       && INTVAL (operands[2]) > 0
                    669:       && INTVAL (operands[2]) <= 3)
                    670:     if (GET_CODE (operands[0]) == REG)
                    671:       {
                    672:        if (GET_CODE (operands[1]) == REG)
                    673:          {
                    674:            if (REGNO (operands[0]) == REGNO (operands[1]))
                    675:              {
                    676:                if (operands[2] == const1_rtx)
                    677:                  return "addd %0,%0";
                    678:                else if (INTVAL (operands[2]) == 2)
                    679:                  return "addd %0,%0\n\taddd %0,%0";
                    680:              }
                    681:            if (operands[2] == const1_rtx)
                    682:              return "movd %1,%0\n\taddd %0,%0";
                    683:            
                    684:            operands[1] = gen_indexed_expr (const0_rtx, operands[1], operands[2]);
                    685:            return "addr %a1,%0";
                    686:          }
                    687:        if (operands[2] == const1_rtx)
                    688:          return "movd %1,%0\n\taddd %0,%0";
                    689:       }
                    690:     else if (GET_CODE (operands[1]) == REG)
                    691:       {
                    692:        operands[1] = gen_indexed_expr (const0_rtx, operands[1], operands[2]);
                    693:        return "addr %a1,%0";
                    694:       }
                    695:     else if (INTVAL (operands[2]) == 1
                    696:             && GET_CODE (operands[1]) == MEM
                    697:             && rtx_equal_p (operands [0], operands[1]))
                    698:       {
                    699:        rtx temp = XEXP (operands[1], 0);
                    700:        
                    701:        if (GET_CODE (temp) == REG
                    702:            || (GET_CODE (temp) == PLUS
                    703:                && GET_CODE (XEXP (temp, 0)) == REG
                    704:                && GET_CODE (XEXP (temp, 1)) == CONST_INT))
                    705:          return "addd %0,%0";
                    706:       }
                    707:     else return "ashd %2,%0";
                    708:   return "ashd %2,%0";
                    709: }

unix.superglobalmegacorp.com

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