Annotation of gcc/output-sparc.c, revision 1.1.1.1

1.1       root        1: /* Subroutines for insn-output.c for Sun SPARC.
                      2:    Copyright (C) 1987 Free Software Foundation, Inc.
                      3:    Contributed by Michael Tiemann ([email protected])
                      4: 
                      5: This file is part of GNU CC.
                      6: 
                      7: GNU CC is distributed in the hope that it will be useful,
                      8: but WITHOUT ANY WARRANTY.  No author or distributor
                      9: accepts responsibility to anyone for the consequences of using it
                     10: or for whether it serves any particular purpose or works at all,
                     11: unless he says so in writing.  Refer to the GNU CC General Public
                     12: License for full details.
                     13: 
                     14: Everyone is granted permission to copy, modify and redistribute
                     15: GNU CC, but only under the conditions described in the
                     16: GNU CC General Public License.   A copy of this license is
                     17: supposed to have been given to you along with GNU CC so you
                     18: can know your rights and responsibilities.  It should be in a
                     19: file named COPYING.  Among other things, the copyright notice
                     20: and this notice must be preserved on all copies.  */
                     21: 
                     22: /* Global variables for machine-dependend things.  */
                     23: 
                     24: /* This should go away if we pass floats to regs via
                     25:    the stack instead of the frame.  */
                     26: extern int frame_pointer_needed;
                     27: 
                     28: static rtx find_addr_reg ();
                     29: 
                     30: #if 0
                     31: /* RTL expressions that we will cache during the entire compilation.  */
                     32: rtx reg_o0_rtx, reg_o1_rtx, reg_o2_rtx, reg_i7_rtx;
                     33: 
                     34: void
                     35: init_emit_mdep ()
                     36: {
                     37:   /* These may be freely shared.  */
                     38:   reg_o0_rtx = gen_rtx (REG, SImode, 8);
                     39:   reg_o1_rtx = gen_rtx (REG, SImode, 9);
                     40:   reg_o2_rtx = gen_rtx (REG, SImode, 10);
                     41:   reg_i7_rtx = gen_rtx (REG, SImode, 31);
                     42: }
                     43: #endif
                     44: 
                     45: int
                     46: arith_operand (op, mode)
                     47:      rtx op;
                     48:      enum machine_mode mode;
                     49: {
                     50:   return (register_operand (op, mode)
                     51:          || (GET_CODE (op) == CONST_INT && SMALL_INT (op)));
                     52: }
                     53: 
                     54: int
                     55: arith32_operand (op, mode)
                     56:      rtx op;
                     57:      enum machine_mode mode;
                     58: {
                     59:   return (register_operand (op, mode) || GET_CODE (op) == CONST_INT);
                     60: }
                     61: 
                     62: /* Return the best assembler insn template
                     63:    for moving operands[1] into operands[0] as a fullword.  */
                     64: 
                     65: static char *
                     66: singlemove_string (operands)
                     67:      rtx *operands;
                     68: {
                     69:   if (GET_CODE (operands[0]) == MEM)
                     70:     return "st %r1,%0";
                     71:   if (GET_CODE (operands[1]) == MEM)
                     72:     return "ld %1,%0";
                     73:   return "add %1,%%g0,%0";
                     74: }
                     75: 
                     76: /* Output assembler code to perform a doubleword move insn
                     77:    with operands OPERANDS.  */
                     78: 
                     79: char *
                     80: output_move_double (operands)
                     81:      rtx *operands;
                     82: {
                     83:   enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
                     84:   rtx latehalf[2];
                     85:   rtx addreg0 = 0, addreg1 = 0;
                     86: 
                     87:   /* First classify both operands.  */
                     88: 
                     89:   if (REG_P (operands[0]))
                     90:     optype0 = REGOP;
                     91:   else if (offsetable_memref_p (operands[0]))
                     92:     optype0 = OFFSOP;
                     93:   else if (GET_CODE (operands[0]) == MEM)
                     94:     optype0 = MEMOP;
                     95:   else
                     96:     optype0 = RNDOP;
                     97: 
                     98:   if (REG_P (operands[1]))
                     99:     optype1 = REGOP;
                    100:   else if (CONSTANT_P (operands[1])
                    101:           || GET_CODE (operands[1]) == CONST_DOUBLE)
                    102:     optype1 = CNSTOP;
                    103:   else if (offsetable_memref_p (operands[1]))
                    104:     optype1 = OFFSOP;
                    105:   else if (GET_CODE (operands[1]) == MEM)
                    106:     optype0 = MEMOP;
                    107:   else
                    108:     optype1 = RNDOP;
                    109: 
                    110:   /* Check for the cases that the operand constraints are not
                    111:      supposed to allow to happen.  Abort if we get one,
                    112:      because generating code for these cases is painful.  */
                    113: 
                    114:   if (optype0 == RNDOP || optype1 == RNDOP)
                    115:     abort ();
                    116: 
                    117:   /* If an operand is an unoffsettable memory ref, find a register
                    118:      we can increment temporarily to make it refer to the second word.  */
                    119: 
                    120:   if (optype0 == MEMOP)
                    121:     addreg0 = find_addr_reg (operands[0]);
                    122: 
                    123:   if (optype1 == MEMOP)
                    124:     addreg1 = find_addr_reg (operands[1]);
                    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_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 the first move would clobber the source of the second one,
                    160:      do them in the other order.  This happens only for registers;
                    161:      such overlap can't happen in memory unless the user explicitly
                    162:      sets it up, and that is an undefined circumstance.  */
                    163: 
                    164:   if (optype0 == REGOP && optype1 == REGOP
                    165:       && REGNO (operands[0]) == REGNO (latehalf[1]))
                    166:     {
                    167:       /* Make any unoffsetable addresses point at high-numbered word.  */
                    168:       if (addreg0)
                    169:        output_asm_insn ("add %0,0x4,%0", &addreg0);
                    170:       if (addreg1)
                    171:        output_asm_insn ("add %0,0x4,%0", &addreg1);
                    172: 
                    173:       /* Do that word.  */
                    174:       output_asm_insn (singlemove_string (latehalf), latehalf);
                    175: 
                    176:       /* Undo the adds we just did.  */
                    177:       if (addreg0)
                    178:        output_asm_insn ("add %0,-0x4,%0", &addreg0);
                    179:       if (addreg1)
                    180:        output_asm_insn ("add %0,-0x4,%0", &addreg0);
                    181: 
                    182:       /* Do low-numbered word.  */
                    183:       return singlemove_string (operands);
                    184:     }
                    185: 
                    186:   /* Normal case: do the two words, low-numbered first.  */
                    187: 
                    188:   output_asm_insn (singlemove_string (operands), operands);
                    189: 
                    190:   /* Make any unoffsetable addresses point at high-numbered word.  */
                    191:   if (addreg0)
                    192:     output_asm_insn ("add %0,0x4,%0", &addreg0);
                    193:   if (addreg1)
                    194:     output_asm_insn ("add %0,0x4,%0", &addreg1);
                    195: 
                    196:   /* Do that word.  */
                    197:   output_asm_insn (singlemove_string (latehalf), latehalf);
                    198: 
                    199:   /* Undo the adds we just did.  */
                    200:   if (addreg0)
                    201:     output_asm_insn ("add %0,-0x4,%0", &addreg0);
                    202:   if (addreg1)
                    203:     output_asm_insn ("add %0,-0x4,%0", &addreg1);
                    204: 
                    205:   return "";
                    206: }
                    207: 
                    208: static char *
                    209: output_fp_move_double (operands)
                    210:      rtx *operands;
                    211: {
                    212:   if (FP_REG_P (operands[0]))
                    213:     {
                    214:       if (FP_REG_P (operands[1]))
                    215:        {
                    216:          output_asm_insn ("fmovs %1,%0", operands);
                    217:          operands[0] = gen_rtx (REG, VOIDmode, REGNO (operands[0]) + 1);
                    218:          operands[1] = gen_rtx (REG, VOIDmode, REGNO (operands[1]) + 1);
                    219:          return "fmovs %1,%0";
                    220:        }
                    221:       if (GET_CODE (operands[1]) == REG)
                    222: /* No good, since a signal would probably clobber that word on the stack.  */
                    223: /*     return "st %1,[%%sp-8]\n\tldd [%%sp-8],%0"; */
                    224:        {
                    225:          rtx xoperands[2];
                    226:          int offset = - get_frame_size () - 8;
                    227:          xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
                    228:          xoperands[0] = gen_rtx (CONST_INT, VOIDmode, offset + 4);
                    229:          output_asm_insn ("st %1,[%%fp+%0]", xoperands);
                    230:          xoperands[1] = operands[1];
                    231:          xoperands[0] = gen_rtx (CONST_INT, VOIDmode, offset);
                    232:          output_asm_insn ("st %1,[%%fp+%0]", xoperands);
                    233:          xoperands[1] = operands[0];
                    234:          output_asm_insn ("ldd [%%fp+%0],%1", xoperands);
                    235:          return "";
                    236:        }
                    237:       return "ldd %1,%0";
                    238:     }
                    239:   else if (FP_REG_P (operands[1]))
                    240:     {
                    241:       if (GET_CODE (operands[0]) == REG)
                    242: /* No good, since a signal would probably clobber that word on the stack.  */
                    243: /*     return "std %1,[%%sp-8]\n\tldd [%%sp-8],%0"; */
                    244:        {
                    245:          rtx xoperands[2];
                    246:          int offset = - get_frame_size () - 8;
                    247:          xoperands[0] = gen_rtx (CONST_INT, VOIDmode, offset);
                    248:          xoperands[1] = operands[1];
                    249:          output_asm_insn ("st %1,[%%fp+%0]", xoperands);
                    250:          xoperands[1] = operands[0];
                    251:          output_asm_insn ("ld [%%fp+%0],%1", xoperands);
                    252:          xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
                    253:          xoperands[0] = gen_rtx (CONST_INT, VOIDmode, offset + 4);
                    254:          output_asm_insn ("ld [%%fp+%0],%1", xoperands);
                    255:          return "";
                    256:        }
                    257:       return "std %1,%0";
                    258:     }
                    259: }
                    260: 
                    261: /* Return a REG that occurs in ADDR with coefficient 1.
                    262:    ADDR can be effectively incremented by incrementing REG.  */
                    263: 
                    264: static rtx
                    265: find_addr_reg (addr)
                    266:      rtx addr;
                    267: {
                    268:   while (GET_CODE (addr) == PLUS)
                    269:     {
                    270:       if (GET_CODE (XEXP (addr, 0)) == REG)
                    271:        addr = XEXP (addr, 0);
                    272:       if (GET_CODE (XEXP (addr, 1)) == REG)
                    273:        addr = XEXP (addr, 1);
                    274:       if (CONSTANT_P (XEXP (addr, 0)))
                    275:        addr = XEXP (addr, 1);
                    276:       if (CONSTANT_P (XEXP (addr, 1)))
                    277:        addr = XEXP (addr, 0);
                    278:     }
                    279:   if (GET_CODE (addr) == REG)
                    280:     return addr;
                    281:   return 0;
                    282: }
                    283: 
                    284: /* Load the address specified by OPERANDS[3] into the register
                    285:    specified by OPERANDS[0].
                    286: 
                    287:    OPERANDS[3] may be the result of a sum, hence it could either be:
                    288: 
                    289:    (1) CONST
                    290:    (2) REG
                    291:    (2) REG + CONST_INT
                    292:    (3) REG + REG + CONST_INT
                    293: 
                    294:    All cases are handled here.  */
                    295: 
                    296: void
                    297: output_load_address (operands)
                    298:      rtx *operands;
                    299: {
                    300:   rtx base, offset;
                    301: 
                    302:   if (CONSTANT_P (operands[3]))
                    303:     {
                    304:       output_asm_insn ("set %3,%0", operands);
                    305:       return;
                    306:     }
                    307: 
                    308:   if (REG_P (operands[3]))
                    309:     {
                    310:       if (REGNO (operands[0]) != REGNO (operands[3]))
                    311:        output_asm_insn ("mov %3,%0", operands);
                    312:       return;
                    313:     }
                    314: 
                    315:   base = XEXP (operands[3], 0);
                    316:   offset = XEXP (operands[3], 1);
                    317: 
                    318:   if (GET_CODE (base) == CONST_INT)
                    319:     {
                    320:       rtx tmp = base;
                    321:       base = offset;
                    322:       offset = tmp;
                    323:     }
                    324: 
                    325:   if (GET_CODE (offset) != CONST_INT)
                    326:     abort ();
                    327: 
                    328:   if (REG_P (base))
                    329:     {
                    330:       operands[6] = base;
                    331:       operands[7] = offset;
                    332:       if (SMALL_INT (offset))
                    333:        output_asm_insn ("add %6,%7,%0", operands);
                    334:       else
                    335:        output_asm_insn ("set %7,%0\n\tadd %0,%6,%0", operands);
                    336:     }
                    337:   else
                    338:     {
                    339:       operands[6] = XEXP (base, 0);
                    340:       operands[7] = XEXP (base, 1);
                    341:       operands[8] = offset;
                    342: 
                    343:       if (SMALL_INT (offset))
                    344:        output_asm_insn ("add %6,%7,%0\n\tadd %0,%8,%0", operands);
                    345:       else
                    346:        output_asm_insn ("set %8,%0\n\tadd %0,%6,%0\n\tadd %0,%7,%0", operands);
                    347:     }
                    348: }
                    349: 
                    350: char *
                    351: output_block_move (operands)
                    352:      rtx *operands;
                    353: {
                    354:   static int movstrsi_label = 0;
                    355:   int align = 4;
                    356: 
                    357:   rtx xoperands[9];
                    358:   int available[3];
                    359:   int i, j;
                    360: 
                    361:   /* Since we clobber untold things, nix the condition codes.  */
                    362:   CC_STATUS_INIT;
                    363: 
                    364:   /* Get past the MEMs.  */
                    365:   operands[0] = XEXP (operands[0], 0);
                    366:   operands[1] = XEXP (operands[1], 0);
                    367: 
                    368:   xoperands[0] = 0;
                    369:   xoperands[1] = 0;
                    370:   xoperands[2] = 0;
                    371: 
                    372:   available[0] = 1;
                    373:   available[1] = 1;
                    374:   available[2] = 1;
                    375: #if 1
                    376:   /* Prepare to juggle registers if necessary.  */
                    377:   if (REG_P (operands[0]) && (unsigned) (REGNO (operands[0]) - 8) < 3)
                    378:     {
                    379:       xoperands[0] = operands[0];
                    380:       available[REGNO (operands[0]) - 8] = 0;
                    381:     }
                    382:   if (REG_P (operands[1]) && (unsigned) (REGNO (operands[1]) - 8) < 3)
                    383:     {
                    384:       xoperands[1] = operands[1];
                    385:       available[REGNO (operands[1]) - 8] = 0;
                    386:     }
                    387:   if (REG_P (operands[2]) && (unsigned) (REGNO (operands[2]) - 8) < 3)
                    388:     {
                    389:       xoperands[2] = operands[2];
                    390:       available[REGNO (operands[2]) - 8] = 0;
                    391:     }
                    392:   for (i = 0; i < 3; i++)
                    393:     {
                    394:       if (xoperands[i])
                    395:        continue;
                    396:       if (available[0])
                    397:        {
                    398:          xoperands[i] = gen_rtx (REG, SImode, 8);
                    399:          available[0] = 0;
                    400:          continue;
                    401:        }
                    402:       if (available[1])
                    403:        {
                    404:          xoperands[i] = gen_rtx (REG, SImode, 9);
                    405:          available[1] = 0;
                    406:          continue;
                    407:        }
                    408:       xoperands[i] = gen_rtx (REG, SImode, 10);
                    409:       available[2] = 0;
                    410:     }
                    411: #endif
                    412: 
                    413:   /* First, figure out best alignment we may assume.  */
                    414:   if (REG_P (operands[2]))
                    415:     {
                    416:       xoperands[5] = operands[2];
                    417:       output_asm_insn ("sub %5,0x1,%2", xoperands);
                    418:       align = 1;
                    419:     }
                    420:   else
                    421:     {
                    422:       int i = INTVAL (operands[2]);
                    423: 
                    424:       if (i & 1)
                    425:        align = 1;
                    426:       else if (i & 3)
                    427:        align = 2;
                    428: 
                    429:       /* predecrement count.  */
                    430:       i -= align;
                    431:       if (i < 0) abort ();
                    432: 
                    433:       xoperands[5] = gen_rtx (CONST_INT, VOIDmode, i);
                    434: 
                    435:       output_asm_insn ("set %5,%2", xoperands);
                    436:     }
                    437: 
                    438:   /* Now, set up for pipelined operation: dest must contain
                    439:      a pre-incremented address, because its index is pre-decremented.  */
                    440: 
                    441:   xoperands[3] = plus_constant (operands[0], align);
                    442:   output_load_address (xoperands);
                    443: 
                    444:   xoperands[4] = operands[1];
                    445:   output_load_address (xoperands+1);
                    446: 
                    447:   xoperands[3] = gen_rtx (CONST_INT, VOIDmode, movstrsi_label++);
                    448:   xoperands[4] = gen_rtx (CONST_INT, VOIDmode, align);
                    449: 
                    450:   output_asm_insn ("\nLm%3:\n\tld [%1+%2],%%o7\n\tsubcc %2,%4,%2\n\tbge Lm%3\n\tst %%o7,[%0+%2]", xoperands);
                    451:   return "";
                    452: }
                    453: 
                    454: #define ABS(x) ((x) < 0 ? -(x) : x)
                    455: 
                    456: char *
                    457: output_mul_by_constant (insn, operands, unsignedp)
                    458:      rtx insn;
                    459:      rtx *operands;
                    460:      int unsignedp;
                    461: {
                    462:   int c;                       /* Size of constant */
                    463:   int shifts[BITS_PER_WORD];   /* Table of shifts */
                    464:   int p, log;                  /* A power of two, and its log */
                    465:   int d1, d2;                  /* Differences of c and p */
                    466:   int first = 1;               /* True if dst has unknown data in it */
                    467:   int i;
                    468: 
                    469:   c = INTVAL (operands[2]);
                    470:   if (c == 0)
                    471:     {
                    472:       /* should not happen.  */
                    473:       abort ();
                    474:       if (GET_CODE (operands[0]) == MEM)
                    475:        return "st %%g0,%0";
                    476:       return "mov %%g0,%0";
                    477:     }
                    478: 
                    479: #if 0
                    480:   printf ("open coding insn:\n");
                    481:   debug_rtx (insn);
                    482:   printf ("done.\n");
                    483: #endif
                    484: 
                    485:   output_asm_insn ("! start open coded multiply");
                    486: 
                    487:   /* Clear out the table of shifts. */
                    488:   for (i = 0; i < BITS_PER_WORD; ++i)
                    489:     shifts[i] = 0;
                    490: 
                    491:   while (c)
                    492:     {
                    493:       /* Find the power of two nearest ABS(c) */
                    494:       p = 1, log = 0;
                    495:       do
                    496:        {
                    497:          d1 = ABS(c) - p;
                    498:          p *= 2;
                    499:          ++log;
                    500:        }
                    501:       while (p < ABS(c));
                    502:       d2 = p - ABS(c);
                    503: 
                    504:       /* Make an appropriate entry in shifts for p. */
                    505:       if (d2 < d1)
                    506:        {
                    507:          shifts[log] = c < 0 ? -1 : 1;
                    508:          c = c < 0 ? d2 : -d2;
                    509:        }
                    510:       else
                    511:        {
                    512:          shifts[log - 1] = c < 0 ? -1 : 1;
                    513:          c = c < 0 ? -d1 : d1;
                    514:        }
                    515:     }
                    516: 
                    517:   /* For now, use a known clobberable register.  This could
                    518:      be improved by looking at insn, and seeing if we
                    519:      have a dying register contained therein.  */
                    520:   regs_ever_live[15] = 1;
                    521:   operands[3] = gen_rtx (REG, SImode, 15);
                    522: 
                    523:   /* Take care of the first insn in sequence.
                    524:      We know we have at least one. */
                    525: 
                    526:   /* A value of -1 in shifts says to subtract that power of two, and a value
                    527:      of 1 says to add that power of two. */
                    528:   for (i = 0; ; i++)
                    529:     if (shifts[i])
                    530:       {
                    531:        if (i)
                    532:          {
                    533:            operands[2] = gen_rtx (CONST_INT, VOIDmode, i);
                    534:            output_asm_insn ("sll %1,%2,%3", operands);
                    535:          }
                    536:        else if (REGNO (operands[3]) == 15)
                    537:          output_asm_insn ("mov %1,%3", operands);
                    538: 
                    539:        log = i;
                    540:        if (shifts[i] < 0)
                    541:          output_asm_insn ("sub %%g0,%3,%0", operands);
                    542:        else
                    543:          output_asm_insn ("mov %3,%0", operands);
                    544:        break;
                    545:       }
                    546: 
                    547:   /* A value of -1 in shifts says to subtract that power of two, and a value
                    548:      of 1 says to add that power of two--continued.  */
                    549:   for (i += 1; i < BITS_PER_WORD; ++i)
                    550:     if (shifts[i])
                    551:       {
                    552:        if (i - log > 0)
                    553:          {
                    554:            operands[2] = gen_rtx (CONST_INT, VOIDmode, i - log);
                    555:            output_asm_insn ("sll %3,%2,%3", operands);
                    556:          }
                    557:        else
                    558:          {
                    559:            operands[2] = gen_rtx (CONST_INT, VOIDmode, log - i);
                    560:            output_asm_insn ("sra %3,%2,%3", operands);
                    561:          }
                    562:        log = i;
                    563:        if (shifts[i] < 0)
                    564:          output_asm_insn ("sub %0,%3,%0", operands);
                    565:        else
                    566:          output_asm_insn ("add %0,%3,%0", operands);
                    567:       }
                    568: 
                    569:   output_asm_insn ("! end open coded multiply");
                    570: 
                    571:   return "";
                    572: }
                    573: 
                    574: char *
                    575: output_mul_insn (operands, unsignedp)
                    576:      rtx *operands;
                    577:      int unsignedp;
                    578: {
                    579:   int lucky1 = ((unsigned)REGNO (operands[1]) - 8) <= 1;
                    580:   int lucky2 = ((unsigned)REGNO (operands[2]) - 8) <= 1;
                    581: 
                    582:   if (lucky1)
                    583:     if (lucky2)
                    584:       output_asm_insn ("call .mul,2\n\tnop", operands);
                    585:     else
                    586:       {
                    587:        rtx xoperands[2];
                    588:        xoperands[0] = gen_rtx (REG, SImode,
                    589:                                8 ^ (REGNO (operands[1]) == 8));
                    590:        xoperands[1] = operands[2];
                    591:        output_asm_insn ("call .mul,2\n\tmov %1,%0", xoperands);
                    592:       }
                    593:   else if (lucky2)
                    594:     {
                    595:       rtx xoperands[2];
                    596:       xoperands[0] = gen_rtx (REG, SImode,
                    597:                              8 ^ (REGNO (operands[2]) == 8));
                    598:       xoperands[1] = operands[1];
                    599:       output_asm_insn ("call .mul,2\n\tmov %1,%0", xoperands);
                    600:     }
                    601:   else
                    602:     {
                    603:       output_asm_insn ("mov %1,%%o0\n\tcall .mul,2\n\tmov %2,%%o1",
                    604:                       operands);
                    605:     }
                    606: 
                    607:   if (REGNO (operands[0]) == 8)
                    608:     return "";
                    609:   return "mov %%o0,%0";
                    610: }
                    611: 
                    612: #if 0
                    613: /* This function does not properly protect its operands.  */
                    614: char *
                    615: output_arith_insn (operands, name)
                    616:      rtx *operands;
                    617:      char *name;
                    618: {
                    619:   extern struct _iobuf *asm_out_file;
                    620: 
                    621:   /* Does not commute.  */
                    622:   rtx op1 = 0;
                    623:   rtx op2 = 0;
                    624: 
                    625:   abort ();
                    626:   if (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == 8)
                    627:     op1 = operands[1];
                    628:   if (GET_CODE (operands[2]) == REG && REGNO (operands[2]) == 8)
                    629:     op2 = operands[2];
                    630: 
                    631:   if (op1 && op2)
                    632:     {
                    633:       /* ?? should have been done earlier.  */
                    634:       abort ();
                    635:     }
                    636:   else
                    637:     {
                    638:       if (op2)
                    639:        {
                    640:          op1 = operands[1];
                    641:          if (REG_P (op1) && REGNO (op1) == 9)
                    642:            {
                    643:              output_asm_insn ("mov %%o1,%%o2\n\tmov %%o0,%%o1", operands);
                    644:              fprintf (asm_out_file, "\tcall %s,2\n", name);
                    645:              output_asm_insn ("mov %%o2,%%o0", operands);
                    646:              goto done;
                    647:            }
                    648:          output_asm_insn ("mov %%o0,%%o1", operands);
                    649:          if (GET_CODE (op1) == CONST_INT && ! SMALL_INT (op1))
                    650:            {
                    651:              output_asm_insn ("sethi %%hi(%1),%%o0", operands);
                    652:              fprintf (asm_out_file, "\tcall %s,2\n", name);
                    653:              output_asm_insn ("add %%o0,%%lo(%1),%%o0", operands);
                    654:            }
                    655:          else
                    656:            {
                    657:              fprintf (asm_out_file, "\tcall %s,2\n", name);
                    658:              if (GET_CODE (op1) == MEM)
                    659:                output_asm_insn ("ld %1,%%o0", operands);
                    660:              else
                    661:                output_asm_insn ("mov %1,%%o0", operands);
                    662:            }
                    663:        }
                    664:       else if (op1)
                    665:        {
                    666:          op2 = operands[2];
                    667:          if (REG_P (op2) && REGNO (operands[1]) == 9)
                    668:            {
                    669:              fprintf (asm_out_file, "\tcall %s,2\n\tnop\n");
                    670:              goto done;
                    671:            }
                    672:          if (GET_CODE (op2) == CONST_INT && ! SMALL_INT (op2))
                    673:            {
                    674:              output_asm_insn ("sethi %%hi(%2),%%o1", operands);
                    675:              fprintf (asm_out_file, "\tcall %s,2\n", name);
                    676:              output_asm_insn ("add %%o1,%%lo(%2),%%o1", operands);
                    677:            }
                    678:          else
                    679:            {
                    680:              fprintf (asm_out_file, "\tcall %s,2\n", name);
                    681:              if (GET_CODE (op2) == MEM)
                    682:                output_asm_insn ("ld %2,%%o1", operands);
                    683:              else
                    684:                output_asm_insn ("mov %2,%%o1", operands);
                    685:            }
                    686:        }
                    687:       else
                    688:        {
                    689:          op1 = operands[1];
                    690:          op2 = operands[2];
                    691: 
                    692:          if (! REG_P (op2) || REGNO (op2) != 9)
                    693:            if (GET_CODE (op2) == MEM)
                    694:              output_asm_insn ("ld %2,%%o1", operands);
                    695:            else if (GET_CODE (op2) != CONST_INT || SMALL_INT (op2))
                    696:              output_asm_insn ("mov %2,%%o1", operands);
                    697:            else
                    698:              output_asm_insn ("sethi %%hi(%2),%%o1\n\tadd %%o1,%%lo(%2),%%o1", operands);
                    699:          if (GET_CODE (op1) == CONST_INT && ! SMALL_INT (op1))
                    700:            {
                    701:              output_asm_insn ("sethi %%hi(%1),%%o0", operands);
                    702:              fprintf (asm_out_file, "\tcall %s,2\n", name);
                    703:              output_asm_insn ("add %%o0,%%lo(%1),%%o0", operands);
                    704:            }
                    705:          else
                    706:            {
                    707:              fprintf (asm_out_file, "\tcall %s,2\n", name);
                    708:              if (GET_CODE (op1) == MEM)
                    709:                output_asm_insn ("ld %1,%%o0", operands);
                    710:              else
                    711:                output_asm_insn ("mov %1,%%o0", operands);
                    712:            }
                    713:        }
                    714:     done:
                    715:       if (REG_P (operands[0]) && REGNO (operands[0]) == 8)
                    716:        return "";
                    717:       if (GET_CODE (operands[0]) == MEM)
                    718:        return "st %%o0,%0";
                    719:       return "mov %%o0,%0";
                    720:     }
                    721: }
                    722: #endif
                    723: 
                    724: /* Make floating point register f0 contain 0.
                    725:    SIZE is the number of registers (including f0)
                    726:    which should contain 0.  */
                    727: 
                    728: void
                    729: make_f0_contain_0 (size)
                    730:      int size;
                    731: {
                    732:   rtx xoperands[1];
                    733:   int offset = - get_frame_size () - 8;
                    734: 
                    735:   xoperands[0] = gen_rtx (CONST_INT, VOIDmode, offset);
                    736:   if (size == 1)
                    737:     output_asm_insn ("ld [%%fp%0],%%f0", xoperands);
                    738:   else if (size == 2)
                    739:     output_asm_insn ("ldd [%%fp%0],%%f0", xoperands);
                    740: }
                    741: 
                    742: #if 0
                    743: /* This was needed only for the "alloca" instruction.  */
                    744: #include "tree.h"
                    745: 
                    746: int
                    747: tree_uid (node)
                    748:      tree node;
                    749: {
                    750:   return TREE_UID (node);
                    751: }
                    752: #endif
                    753: 

unix.superglobalmegacorp.com

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