Annotation of gcc/config/out-ns32k.c, revision 1.1.1.2

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 1, 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: extern FILE *asm_out_file;
                     23: 
                     24: #define FP_REG_P(X)  (GET_CODE (X) == REG && REGNO (X) > 7 && REGNO (X) < 16)
                     25: 
                     26: /* Generate the rtx that comes from an address expression in the md file */
                     27: /* The expression to be build is BASE[INDEX:SCALE].  To recognize this,
                     28:    scale must be converted from an exponent (from ASHIFT) to a
                     29:    muliplier (for MULT). */
                     30: rtx
                     31: gen_indexed_expr (base, index, scale)
                     32:      rtx base, index, scale;
                     33: {
                     34:   rtx addr;
                     35: 
                     36:   /* This generates an illegal addressing mode, if BASE is
                     37:      fp or sp.  This is handled by PRINT_OPERAND_ADDRESS.  */
                     38:   if (GET_CODE (base) != REG && GET_CODE (base) != CONST_INT)
                     39:     base = gen_rtx (MEM, SImode, base);
                     40:   addr = gen_rtx (MULT, SImode, index,
                     41:                  gen_rtx (CONST_INT, VOIDmode, 1 << INTVAL (scale)));
                     42:   addr = gen_rtx (PLUS, SImode, base, addr);
                     43:   return addr;
                     44: }
                     45: 
                     46: /* Return 1 if OP is a valid constant int. These can be modeless
                     47:    (void mode), so we do not mess with their modes.
                     48: 
                     49:    The main use of this function is as a predicate in match_operand
                     50:    expressions in the machine description.  */
                     51: 
                     52: int
                     53: const_int (op, mode)
                     54:      register rtx op;
                     55:      enum machine_mode mode;
                     56: {
                     57:   return (GET_CODE (op) == CONST_INT);
                     58: }
                     59: 
                     60: /* Return 1 if OP is a valid operand of mode MODE.  This
                     61:    predicate rejects operands which do not have a mode
                     62:    (such as CONST_INT which are VOIDmode).  */
                     63: int
                     64: reg_or_mem_operand (op, mode)
                     65:      register rtx op;
                     66:      enum machine_mode mode;
                     67: {
                     68:   return (GET_MODE (op) == mode
                     69:          && (GET_CODE (op) == REG
                     70:              || GET_CODE (op) == SUBREG
                     71:              || GET_CODE (op) == MEM));
                     72: }
                     73: 
                     74: /* Return the best assembler insn template
                     75:    for moving operands[1] into operands[0] as a fullword.  */
                     76: 
                     77: static char *
                     78: singlemove_string (operands)
                     79:      rtx *operands;
                     80: {
                     81:   if (GET_CODE (operands[1]) == CONST_INT
                     82:       && INTVAL (operands[1]) <= 7
                     83:       && INTVAL (operands[1]) >= -8)
                     84:     return "movqd %1,%0";
                     85:   return "movd %1,%0";
                     86: }
                     87: 
                     88: char *
                     89: output_move_double (operands)
                     90:      rtx *operands;
                     91: {
                     92:   enum anon1 { REGOP, OFFSOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
                     93:   rtx latehalf[2];
                     94: 
                     95:   /* First classify both operands.  */
                     96: 
                     97:   if (REG_P (operands[0]))
                     98:     optype0 = REGOP;
                     99:   else if (offsettable_memref_p (operands[0]))
                    100:     optype0 = OFFSOP;
                    101:   else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
                    102:     optype0 = POPOP;
                    103:   else
                    104:     optype0 = RNDOP;
                    105: 
                    106:   if (REG_P (operands[1]))
                    107:     optype1 = REGOP;
1.1.1.2 ! root      108:   else if (CONSTANT_P (operands[1])
1.1       root      109:           || GET_CODE (operands[1]) == CONST_DOUBLE)
                    110:     optype1 = CNSTOP;
                    111:   else if (offsettable_memref_p (operands[1]))
                    112:     optype1 = OFFSOP;
                    113:   else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
                    114:     optype1 = POPOP;
                    115:   else
                    116:     optype1 = RNDOP;
                    117: 
                    118:   /* Check for the cases that the operand constraints are not
                    119:      supposed to allow to happen.  Abort if we get one,
                    120:      because generating code for these cases is painful.  */
                    121: 
                    122:   if (optype0 == RNDOP || optype1 == RNDOP)
                    123:     abort ();
                    124: 
                    125:   /* Ok, we can do one word at a time.
                    126:      Normally we do the low-numbered word first,
                    127:      but if either operand is autodecrementing then we
                    128:      do the high-numbered word first.
                    129: 
                    130:      In either case, set up in LATEHALF the operands to use
                    131:      for the high-numbered word and in some cases alter the
                    132:      operands in OPERANDS to be suitable for the low-numbered word.  */
                    133: 
                    134:   if (optype0 == REGOP)
                    135:     latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
                    136:   else if (optype0 == OFFSOP)
                    137:     latehalf[0] = adj_offsettable_operand (operands[0], 4);
                    138:   else
                    139:     latehalf[0] = operands[0];
                    140: 
                    141:   if (optype1 == REGOP)
                    142:     latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
                    143:   else if (optype1 == OFFSOP)
                    144:     latehalf[1] = adj_offsettable_operand (operands[1], 4);
                    145:   else if (optype1 == CNSTOP)
                    146:     {
1.1.1.2 ! root      147:       if (CONSTANT_P (operands[1]))
1.1       root      148:        latehalf[1] = const0_rtx;
                    149:       else if (GET_CODE (operands[1]) == CONST_DOUBLE)
                    150:        {
                    151:          latehalf[1] = gen_rtx (CONST_INT, VOIDmode,
                    152:                                 CONST_DOUBLE_HIGH (operands[1]));
                    153:          operands[1] = gen_rtx (CONST_INT, VOIDmode,
                    154:                                 CONST_DOUBLE_LOW (operands[1]));
                    155:        }
                    156:     }
                    157:   else
                    158:     latehalf[1] = operands[1];
                    159: 
                    160:   /* If one or both operands autodecrementing,
                    161:      do the two words, high-numbered first.  */
                    162: 
                    163:   if (optype0 == POPOP || optype1 == POPOP)
                    164:     {
                    165:       output_asm_insn (singlemove_string (latehalf), latehalf);
                    166:       return singlemove_string (operands);
                    167:     }
                    168: 
                    169:   /* Not autodecrementing.  Do the two words, low-numbered first.  */
                    170: 
                    171:   output_asm_insn (singlemove_string (operands), operands);
                    172: 
                    173:   operands[0] = latehalf[0];
                    174:   operands[1] = latehalf[1];
                    175:   return singlemove_string (operands);
                    176: }
                    177: 
                    178: int
                    179: check_reg (oper, reg)
                    180:      rtx oper;
                    181:      int reg;
                    182: {
                    183:   register int i;
                    184: 
                    185:   if (oper == 0)
                    186:     return 0;
                    187:   switch (GET_CODE(oper))
                    188:     {
                    189:     case REG:
                    190:       return (REGNO(oper) == reg) ? 1 : 0;
                    191:     case MEM:
                    192:       return check_reg(XEXP(oper, 0), reg);
                    193:     case PLUS:
                    194:     case MULT:
                    195:       return check_reg(XEXP(oper, 0), reg) || check_reg(XEXP(oper, 1), reg);
                    196:     }
                    197:   return 0;
                    198: }
                    199: 
                    200: /* PRINT_OPERAND_ADDRESS is defined to call this function,
                    201:    which is easier to debug than putting all the code in
                    202:    a macro definition in tm-ns32k.h .  */
                    203: 
                    204: /* Nonzero if we have printed a base register.
                    205:    If zero, on some systems, it means `(sb)' must be printed.  */
                    206: int paren_base_reg_printed = 0;
                    207: 
                    208: print_operand_address (file, addr)
                    209:      register FILE *file;
                    210:      register rtx addr;
                    211: {
                    212:   register rtx reg1, reg2, breg, ireg;
                    213:   rtx offset;
                    214:   static char scales[] = { 'b', 'w', 'd', 0, 'q', };
                    215: 
                    216:  retry:
                    217:   switch (GET_CODE (addr))
                    218:     {
                    219:     case MEM:
                    220:       addr = XEXP (addr, 0);
                    221:       if (GET_CODE (addr) == REG)
                    222:        if (REGNO (addr) == STACK_POINTER_REGNUM)
                    223:          { fprintf (file, "tos"); break; }
                    224:        else
                    225:          { fprintf (file, "%s", reg_names[REGNO (addr)]); break; }
                    226:       else if (CONSTANT_P (addr))
                    227:        { output_addr_const (file, addr); break; }
                    228:       else if (GET_CODE (addr) == MULT)
                    229:        { fprintf (file, "@0"); ireg = addr; goto print_index; }
                    230:       else if (GET_CODE (addr) == MEM)
                    231:        {
                    232:          addr = XEXP (addr, 0);
                    233:          if (GET_CODE (addr) == PLUS)
                    234:            {
                    235:              offset = XEXP (addr, 1);
                    236:              addr = XEXP (addr, 0);
                    237:            }
                    238:          else
                    239:            {
                    240:              offset = const0_rtx;
                    241:            }
                    242:          output_addr_const (file, offset);
                    243:          fprintf (file, "(%s)", reg_names[REGNO (addr)]);
                    244:          break;
                    245:        }
                    246: 
                    247:       if (GET_CODE (addr) != PLUS)
                    248:        abort ();
                    249: 
                    250:       goto retry;
                    251: 
                    252:     case REG:
                    253:       if (REGNO (addr) == STACK_POINTER_REGNUM)
                    254:        fprintf (file, "tos");
                    255:       else
                    256:        fprintf (file, "0(%s)", reg_names[REGNO (addr)]);
                    257:       break;
                    258: 
                    259:     case PRE_DEC:
                    260:     case POST_INC:
                    261:       fprintf (file, "tos");
                    262:       break;
                    263: 
                    264:     case MULT:
                    265:       fprintf (file, "@0");
                    266:       ireg = addr; /* [rX:Y] */
                    267:       goto print_index;
                    268:       break;
                    269: 
                    270:     case PLUS:
                    271:       reg1 = 0;        reg2 = 0;
                    272:       ireg = 0;        breg = 0;
                    273:       offset = const0_rtx;
                    274:       if (CONSTANT_ADDRESS_P (XEXP (addr, 0)))
                    275:        {
                    276:          offset = XEXP (addr, 0);
                    277:          addr = XEXP (addr, 1);
                    278:        }
                    279:       else if (CONSTANT_ADDRESS_P (XEXP (addr, 1)))
                    280:        {
                    281:          offset = XEXP (addr, 1);
                    282:          addr = XEXP (addr, 0);
                    283:        }
                    284:       if (GET_CODE (addr) != PLUS) ;
                    285:       else if (GET_CODE (XEXP (addr, 0)) == MULT)
                    286:        {
                    287:          reg1 = XEXP (addr, 0);
                    288:          addr = XEXP (addr, 1);
                    289:        }
                    290:       else if (GET_CODE (XEXP (addr, 1)) == MULT)
                    291:        {
                    292:          reg1 = XEXP (addr, 1);
                    293:          addr = XEXP (addr, 0);
                    294:        }
                    295:       /* The case for memory is somewhat tricky:  to get
                    296:         a MEM here, the only RTX formats that could
                    297:         get here are either (modulo commutativity)
                    298:           (PLUS (PLUS (REG *MEM)) CONST) -or-
                    299:           (PLUS (PLUS (CONST REG/MULT)) *MEM)
                    300:         We take advantage of that knowledge here.  */
                    301:       else if (GET_CODE (XEXP (addr, 0)) == MEM
                    302:               || GET_CODE (XEXP (addr, 1)) == MEM)
                    303:        {
                    304:          rtx temp;
                    305: 
                    306:          if (GET_CODE (XEXP (addr, 0)) == MEM)
                    307:            {
                    308:              temp = XEXP (addr, 1);
                    309:              addr = XEXP (addr, 0);
                    310:            }
                    311:          else
                    312:            {
                    313:              temp = XEXP (addr, 0);
                    314:              addr = XEXP (addr, 1);
                    315:            }
                    316: 
                    317:          if (GET_CODE (temp) == REG)
                    318:            {
                    319:              reg1 = temp;
                    320:            }
                    321:          else
                    322:            {
                    323:              if (GET_CODE (temp) != PLUS)
                    324:                abort ();
                    325: 
                    326:              if (GET_CODE (XEXP (temp, 0)) == MULT)
                    327:                {
                    328:                  reg1 = XEXP (temp, 0);
                    329:                  offset = XEXP (temp, 1);
                    330:                }
                    331:              if (GET_CODE (XEXP (temp, 1)) == MULT)
                    332:                {
                    333:                  reg1 = XEXP (temp, 1);
                    334:                  offset = XEXP (temp, 0);
                    335:                }
                    336:              else
                    337:                abort ();
                    338:            }
                    339:        }
                    340:       else if (GET_CODE (XEXP (addr, 0)) == REG
                    341:               || GET_CODE (XEXP (addr, 1)) == REG)
                    342:        {
                    343:          rtx temp;
                    344: 
                    345:          if (GET_CODE (XEXP (addr, 0)) == REG)
                    346:            {
                    347:              temp = XEXP (addr, 0);
                    348:              addr = XEXP (addr, 1);
                    349:            }
                    350:          else
                    351:            {
                    352:              temp = XEXP (addr, 1);
                    353:              addr = XEXP (addr, 0);
                    354:            }
                    355: 
                    356:          if (GET_CODE (addr) == REG)
                    357:            {
                    358:              if (REGNO (temp) >= FRAME_POINTER_REGNUM)
                    359:                { reg1 = addr; addr = temp; }
                    360:              else
                    361:                { reg1 = temp; }
                    362:            }
                    363:          else if (CONSTANT_P (addr))
                    364:            {
                    365:              if (GET_CODE (offset) == CONST_INT
                    366:                  && INTVAL (offset))
                    367:                offset = plus_constant (addr, INTVAL (offset));
                    368:              addr = temp;
                    369:            }
                    370:          else if (GET_CODE (addr) != PLUS)
                    371:            abort ();
                    372:          else
                    373:            {
                    374:              if (CONSTANT_ADDRESS_P (XEXP (addr, 0)))
                    375:                {
                    376:                  offset = XEXP (addr, 0);
                    377:                  addr = XEXP (addr, 1);
                    378:                }
                    379:              else if (CONSTANT_ADDRESS_P (XEXP (addr, 1)))
                    380:                {
                    381:                  offset = XEXP (addr, 1);
                    382:                  addr = XEXP (addr, 0);
                    383:                }
                    384:              else abort ();
                    385: 
                    386:              if (GET_CODE (addr) == REG)
                    387:                {
                    388:                  if (REGNO (temp) >= FRAME_POINTER_REGNUM)
                    389:                    { reg1 = addr; addr = temp; }
                    390:                  else
                    391:                    { reg1 = temp; }
                    392:                }
                    393:              else
                    394:                reg1 = temp;
                    395:            }
                    396:        }
                    397: 
                    398:       if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT)
                    399:        { if (reg1 == 0) reg1 = addr; else reg2 = addr; addr = 0; }
                    400:       if (addr != 0)
                    401:        {
                    402:          if (CONSTANT_P (addr) && reg1)
                    403:            {
                    404:              /* OFFSET comes second, to prevent outputting
                    405:                 operands of the form INT+SYMBOL+INT.
                    406:                 The Genix assembler dies on them.  */
                    407:              output_addr_const (file, addr);
                    408:              if (offset != const0_rtx)
                    409:                {
                    410:                  putc ('+', file);
                    411:                  output_addr_const (file, offset);
                    412:                }
                    413:              ireg = reg1;
                    414:              goto print_index;
                    415:            }
                    416:          else if (GET_CODE (addr) != MEM)
                    417:            abort ();
                    418: 
                    419:          output_addr_const (file, offset);
                    420: #ifndef SEQUENT_ADDRESS_BUG
                    421:          putc ('(', file);
                    422:          paren_base_reg_printed = 0;
                    423:          output_address (addr);
                    424: #ifdef SEQUENT_BASE_REGS
                    425:          if (!paren_base_reg_printed)
                    426:            fprintf (file, "(sb)");
                    427: #endif
                    428:          putc (')', file);
                    429: #else /* SEQUENT_ADDRESS_BUG */
                    430:          if ((GET_CODE (offset) == SYMBOL_REF
                    431:               || GET_CODE (offset) == CONST)
                    432:              && GET_CODE (addr) == REG)
                    433:            {
                    434:              if (reg1) abort ();
                    435:              fprintf (file, "[%s:b]", reg_names[REGNO (addr)]);
                    436:            }
                    437:          else
                    438:            {
                    439:              putc ('(', file);
                    440:              paren_base_reg_printed = 0;
                    441:              output_address (addr);
                    442: #ifdef SEQUENT_BASE_REGS
                    443:              if (!paren_base_reg_printed)
                    444:                fprintf (file, "(sb)");
                    445: #endif
                    446:              putc (')', file);
                    447:            }
                    448: #endif /* SEQUENT_ADDRESS_BUG */
                    449:          ireg = reg1;
                    450:          goto print_index;
                    451:        }
                    452:       else addr = offset;
                    453:       if (reg1 && GET_CODE (reg1) == MULT)
                    454:        { breg = reg2; ireg = reg1; }
                    455:       else if (reg2 && GET_CODE (reg2) == MULT)
                    456:        { breg = reg1; ireg = reg2; }
                    457:       else if (reg2 || GET_CODE (addr) == MEM)
                    458:        { breg = reg2; ireg = reg1; }
                    459:       else
                    460:        { breg = reg1; ireg = reg2; }
                    461:       if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF)
                    462:         {
                    463:          int scale;
                    464:          if (GET_CODE (ireg) == MULT)
                    465:            {
                    466:              scale = INTVAL (XEXP (ireg, 1)) >> 1;
                    467:              ireg = XEXP (ireg, 0);
                    468:            }
                    469:          else scale = 0;
                    470:          output_asm_label (addr);
                    471:          fprintf (file, "[%s:%c]",
                    472:                   reg_names[REGNO (ireg)], scales[scale]);
                    473:          break;
                    474:        }
                    475:       if (ireg && breg && offset == const0_rtx)
                    476:        fprintf (file, "0(%s)", reg_names[REGNO (breg)]);
                    477:       else
                    478:        {
                    479:          if (addr != 0)
                    480:            {
                    481:              if (ireg != 0 && breg == 0
                    482:                  && GET_CODE (offset) == CONST_INT) putc('@', file);
                    483:              output_addr_const (file, offset);
                    484:            }
                    485:          if (breg != 0)
                    486:            {
                    487:              if (GET_CODE (breg) != REG) abort ();
                    488: #ifndef SEQUENT_ADDRESS_BUG
                    489:              fprintf (file, "(%s)", reg_names[REGNO (breg)]);
                    490:              paren_base_reg_printed = -1;
                    491: #else
                    492:              if (GET_CODE (offset) == SYMBOL_REF || GET_CODE (offset) == CONST)
                    493:                {
                    494:                  if (ireg) abort ();
                    495:                  fprintf (file, "[%s:b]", reg_names[REGNO (breg)]);
                    496:                }
                    497:              else
                    498:                {
                    499:                  fprintf (file, "(%s)", reg_names[REGNO (breg)]);
                    500:                  paren_base_reg_printed = -1;
                    501:                }
                    502: #endif
                    503:            }
                    504:        }
                    505:   print_index:
                    506:       if (ireg != 0)
                    507:        {
                    508:          int scale;
                    509:          if (GET_CODE (ireg) == MULT)
                    510:            {
                    511:              scale = INTVAL (XEXP (ireg, 1)) >> 1;
                    512:              ireg = XEXP (ireg, 0);
                    513:            }
                    514:          else scale = 0;
                    515:          if (GET_CODE (ireg) != REG) abort ();
                    516:          fprintf (file, "[%s:%c]",
                    517:                   reg_names[REGNO (ireg)],
                    518:                   scales[scale]);
                    519:        }
                    520:       break;
                    521:     default:
                    522:       output_addr_const (file, addr);
                    523:     }
                    524: }
                    525: 
                    526: /* National 32032 shifting is so bad that we can get
                    527:    better performance in many common cases by using other
                    528:    techniques.  */
                    529: char *
                    530: output_shift_insn (operands)
                    531:      rtx *operands;
                    532: {
                    533:   if (GET_CODE (operands[2]) == CONST_INT
                    534:       && INTVAL (operands[2]) > 0
                    535:       && INTVAL (operands[2]) <= 3)
                    536:     if (GET_CODE (operands[0]) == REG)
                    537:       {
                    538:        if (GET_CODE (operands[1]) == REG)
                    539:          {
                    540:            if (REGNO (operands[0]) == REGNO (operands[1]))
                    541:              {
                    542:                if (operands[2] == const1_rtx)
                    543:                  return "addd %0,%0";
                    544:                else if (INTVAL (operands[2]) == 2)
                    545:                  return "addd %0,%0\n\taddd %0,%0";
                    546:              }
                    547:            if (operands[2] == const1_rtx)
                    548:              return "movd %1,%0\n\taddd %0,%0";
                    549: 
                    550:            operands[1] = gen_indexed_expr (const0_rtx, operands[1], operands[2]);
                    551:            return "addr %a1,%0";
                    552:          }
                    553:        if (operands[2] == const1_rtx)
                    554:          return "movd %1,%0\n\taddd %0,%0";
                    555:       }
                    556:     else if (GET_CODE (operands[1]) == REG)
                    557:       {
                    558:        operands[1] = gen_indexed_expr (const0_rtx, operands[1], operands[2]);
                    559:        return "addr %a1,%0";
                    560:       }
                    561:     else if (INTVAL (operands[2]) == 1
                    562:             && GET_CODE (operands[1]) == MEM
                    563:             && rtx_equal_p (operands [0], operands[1]))
                    564:       {
                    565:        rtx temp = XEXP (operands[1], 0);
                    566: 
                    567:        if (GET_CODE (temp) == REG
                    568:            || (GET_CODE (temp) == PLUS
                    569:                && GET_CODE (XEXP (temp, 0)) == REG
                    570:                && GET_CODE (XEXP (temp, 1)) == CONST_INT))
                    571:          return "addd %0,%0";
                    572:       }
                    573:     else return "ashd %2,%0";
                    574:   return "ashd %2,%0";
                    575: }

unix.superglobalmegacorp.com

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