Annotation of researchv10dc/cmd/gcc/output-ns32k.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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