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

1.1       root        1: /* Subroutines for insn-output.c for Sun SPARC.
1.1.1.4   root        2:    Copyright (C) 1987, 1988 Free Software Foundation, Inc.
1.1       root        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
1.1.1.4   root       25:    the stack instead of the frame, and if we learn how
                     26:    to renumber all the registers when we don't do a save (hard!).  */
1.1       root       27: extern int frame_pointer_needed;
                     28: 
                     29: static rtx find_addr_reg ();
                     30: 
1.1.1.4   root       31: /* Return non-zero if this pattern, as a source to a "SET",
                     32:    is known to yield an instruction of unit size.  */
                     33: int
                     34: single_insn_src_p (op, mode)
                     35:      rtx op;
                     36:      enum machine_mode mode;
1.1       root       37: {
1.1.1.4   root       38:   switch (GET_CODE (op))
                     39:     {
                     40:     case CONST_INT:
                     41:       if (SMALL_INT (op))
                     42:        return 1;
                     43:       return 0;
                     44: 
                     45:     case REG:
                     46:     case MEM:
                     47:       return 1;
                     48: 
                     49:       /* We never need to negate or complement constants.  */
                     50:     case NOT:
                     51:     case NEG:
                     52:       return 1;
                     53: 
                     54:     case PLUS:
                     55:     case MINUS:
                     56:     case AND:
                     57:     case IOR:
                     58:     case XOR:
                     59:     case LSHIFT:
                     60:     case ASHIFT:
                     61:     case ASHIFTRT:
                     62:     case LSHIFTRT:
                     63:       if ((GET_CODE (XEXP (op, 0)) == CONST_INT && ! SMALL_INT (XEXP (op, 0)))
                     64:          || (GET_CODE (XEXP (op, 1)) == CONST_INT && ! SMALL_INT (XEXP (op, 1))))
                     65:        return 0;
                     66:       return 1;
                     67: 
                     68:     case SUBREG:
                     69:       if (SUBREG_WORD (op) != 0)
                     70:        return 0;
                     71:       return single_insn_src_p (SUBREG_REG (op), mode);
                     72: 
                     73:     case SIGN_EXTEND:
                     74:     case ZERO_EXTEND:
                     75:       /* Lazy... could check for these.  */
                     76:       return 0;
                     77: 
                     78:       /* Not doing floating point, since they probably
                     79:         take longer than the branch slot they might fill.  */
                     80:     case FLOAT_EXTEND:
                     81:     case FLOAT_TRUNCATE:
                     82:     case FLOAT:
                     83:     case FIX:
                     84:     case UNSIGNED_FLOAT:
                     85:     case UNSIGNED_FIX:
                     86:       return 0;
                     87: 
                     88:     default:
                     89:       return 0;
                     90:     }
1.1       root       91: }
1.1.1.4   root       92: 
1.1.1.5   root       93: /* Return truth value of whether OP can be used as an operands in a three
                     94:    address arithmetic insn (such as add %o1,7,%l2) of mode MODE.  */
1.1       root       95: 
                     96: int
                     97: arith_operand (op, mode)
                     98:      rtx op;
                     99:      enum machine_mode mode;
                    100: {
                    101:   return (register_operand (op, mode)
                    102:          || (GET_CODE (op) == CONST_INT && SMALL_INT (op)));
                    103: }
                    104: 
1.1.1.5   root      105: /* Return truth value of whether OP can be used as an operand in a two
                    106:    address arithmetic insn (such as set 123456,%o4) of mode MODE.  */
1.1.1.4   root      107: 
1.1       root      108: int
                    109: arith32_operand (op, mode)
                    110:      rtx op;
                    111:      enum machine_mode mode;
                    112: {
                    113:   return (register_operand (op, mode) || GET_CODE (op) == CONST_INT);
                    114: }
                    115: 
1.1.1.5   root      116: /* Return truth value of whether OP is a integer which fits the
                    117:    range constraining immediate operands in three-address insns.  */
                    118: 
1.1.1.3   root      119: int
                    120: small_int (op, mode)
                    121:      rtx op;
                    122:      enum machine_mode mode;
                    123: {
                    124:   return (GET_CODE (op) == CONST_INT && SMALL_INT (op));
                    125: }
                    126: 
1.1       root      127: /* Return the best assembler insn template
                    128:    for moving operands[1] into operands[0] as a fullword.  */
                    129: 
                    130: static char *
                    131: singlemove_string (operands)
                    132:      rtx *operands;
                    133: {
                    134:   if (GET_CODE (operands[0]) == MEM)
                    135:     return "st %r1,%0";
                    136:   if (GET_CODE (operands[1]) == MEM)
                    137:     return "ld %1,%0";
1.1.1.3   root      138:   return "mov %1,%0";
1.1       root      139: }
                    140: 
                    141: /* Output assembler code to perform a doubleword move insn
                    142:    with operands OPERANDS.  */
                    143: 
                    144: char *
                    145: output_move_double (operands)
                    146:      rtx *operands;
                    147: {
                    148:   enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
                    149:   rtx latehalf[2];
                    150:   rtx addreg0 = 0, addreg1 = 0;
                    151: 
                    152:   /* First classify both operands.  */
                    153: 
                    154:   if (REG_P (operands[0]))
                    155:     optype0 = REGOP;
                    156:   else if (offsetable_memref_p (operands[0]))
                    157:     optype0 = OFFSOP;
                    158:   else if (GET_CODE (operands[0]) == MEM)
                    159:     optype0 = MEMOP;
                    160:   else
                    161:     optype0 = RNDOP;
                    162: 
                    163:   if (REG_P (operands[1]))
                    164:     optype1 = REGOP;
                    165:   else if (CONSTANT_P (operands[1])
                    166:           || GET_CODE (operands[1]) == CONST_DOUBLE)
                    167:     optype1 = CNSTOP;
                    168:   else if (offsetable_memref_p (operands[1]))
                    169:     optype1 = OFFSOP;
                    170:   else if (GET_CODE (operands[1]) == MEM)
                    171:     optype0 = MEMOP;
                    172:   else
                    173:     optype1 = RNDOP;
                    174: 
                    175:   /* Check for the cases that the operand constraints are not
                    176:      supposed to allow to happen.  Abort if we get one,
                    177:      because generating code for these cases is painful.  */
                    178: 
                    179:   if (optype0 == RNDOP || optype1 == RNDOP)
                    180:     abort ();
                    181: 
                    182:   /* If an operand is an unoffsettable memory ref, find a register
                    183:      we can increment temporarily to make it refer to the second word.  */
                    184: 
                    185:   if (optype0 == MEMOP)
                    186:     addreg0 = find_addr_reg (operands[0]);
                    187: 
                    188:   if (optype1 == MEMOP)
                    189:     addreg1 = find_addr_reg (operands[1]);
                    190: 
                    191:   /* Ok, we can do one word at a time.
                    192:      Normally we do the low-numbered word first,
                    193:      but if either operand is autodecrementing then we
                    194:      do the high-numbered word first.
                    195: 
                    196:      In either case, set up in LATEHALF the operands to use
                    197:      for the high-numbered word and in some cases alter the
                    198:      operands in OPERANDS to be suitable for the low-numbered word.  */
                    199: 
                    200:   if (optype0 == REGOP)
                    201:     latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
                    202:   else if (optype0 == OFFSOP)
                    203:     latehalf[0] = adj_offsetable_operand (operands[0], 4);
                    204:   else
                    205:     latehalf[0] = operands[0];
                    206: 
                    207:   if (optype1 == REGOP)
                    208:     latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
                    209:   else if (optype1 == OFFSOP)
                    210:     latehalf[1] = adj_offsetable_operand (operands[1], 4);
                    211:   else if (optype1 == CNSTOP)
                    212:     {
                    213:       if (CONSTANT_P (operands[1]))
                    214:        latehalf[1] = const0_rtx;
                    215:       else if (GET_CODE (operands[1]) == CONST_DOUBLE)
                    216:        {
                    217:          latehalf[1] = gen_rtx (CONST_INT, VOIDmode, XINT (operands[1], 1));
                    218:          operands[1] = gen_rtx (CONST_INT, VOIDmode, XINT (operands[1], 0));
                    219:        }
                    220:     }
                    221:   else
                    222:     latehalf[1] = operands[1];
                    223: 
                    224:   /* If the first move would clobber the source of the second one,
1.1.1.3   root      225:      do them in the other order.
                    226: 
                    227:      RMS says "This happens only for registers;
1.1       root      228:      such overlap can't happen in memory unless the user explicitly
1.1.1.3   root      229:      sets it up, and that is an undefined circumstance."
                    230: 
                    231:      but it happens on the sparc when loading parameter registers,
                    232:      so I am going to define that circumstance, and make it work
                    233:      as expected.  */
                    234: 
                    235:   /* Easy case: try moving both words at once.  */
                    236:   if ((optype0 == REGOP && optype1 != REGOP
                    237:        && (REGNO (operands[0]) & 1) == 0)
                    238:       || (optype0 != REGOP && optype1 == REGOP
                    239:          && (REGNO (operands[1]) & 1) == 0))
                    240:     {
                    241:       rtx op1, op2;
                    242:       rtx base = 0, offset = const0_rtx;
1.1       root      243: 
1.1.1.3   root      244:       if (optype0 == REGOP)
                    245:        op1 = operands[0], op2 = XEXP (operands[1], 0);
                    246:       else
                    247:        op1 = operands[1], op2 = XEXP (operands[0], 0);
                    248: 
1.1.1.4   root      249:       /* Trust global variables.  */
1.1.1.3   root      250:       if (GET_CODE (op2) == SYMBOL_REF
                    251:          || GET_CODE (op2) == CONST
                    252:          || GET_CODE (op2) == REG)
1.1.1.4   root      253:        {
                    254:          if (op1 == operands[0])
                    255:            return "ldd %1,%0";
                    256:          else
                    257:            return "std %1,%0";
                    258:        }
1.1.1.3   root      259: 
1.1.1.4   root      260:       if (GET_CODE (op2) == PLUS)
                    261:        {
                    262:          if (GET_CODE (XEXP (op2, 0)) == REG)
                    263:            base = XEXP (op2, 0), offset = XEXP (op2, 1);
                    264:          else if (GET_CODE (XEXP (op2, 1)) == REG)
                    265:            base = XEXP (op2, 1), offset = XEXP (op2, 0);
                    266:        }
                    267: 
                    268:       /* Trust round enough offsets from the stack or frame pointer.  */
1.1.1.3   root      269:       if (base
1.1.1.4   root      270:          && (REGNO (base) == FRAME_POINTER_REGNUM
                    271:              || REGNO (base) == STACK_POINTER_REGNUM))
                    272:        {
                    273:          if (GET_CODE (offset) == CONST_INT
                    274:              && (INTVAL (offset) & 0x7) == 0)
                    275:            {
                    276:              if (op1 == operands[0])
                    277:                return "ldd %1,%0";
                    278:              else
                    279:                return "std %1,%0";
                    280:            }
                    281:        }
                    282:       else
                    283:        {
                    284:          /* We know structs not on the stack are properly aligned.  */
1.1.1.6 ! root      285:          if (MEM_IN_STRUCT_P (operands[1]))
1.1.1.4   root      286:            return "ldd %1,%0";
1.1.1.6 ! root      287:          else if (MEM_IN_STRUCT_P (operands[0]))
1.1.1.4   root      288:            return "std %1,%0";
                    289:        }
1.1.1.3   root      290:     }
1.1.1.4   root      291: 
1.1       root      292:   if (optype0 == REGOP && optype1 == REGOP
                    293:       && REGNO (operands[0]) == REGNO (latehalf[1]))
                    294:     {
                    295:       /* Make any unoffsetable addresses point at high-numbered word.  */
                    296:       if (addreg0)
                    297:        output_asm_insn ("add %0,0x4,%0", &addreg0);
                    298:       if (addreg1)
                    299:        output_asm_insn ("add %0,0x4,%0", &addreg1);
                    300: 
                    301:       /* Do that word.  */
                    302:       output_asm_insn (singlemove_string (latehalf), latehalf);
                    303: 
                    304:       /* Undo the adds we just did.  */
                    305:       if (addreg0)
                    306:        output_asm_insn ("add %0,-0x4,%0", &addreg0);
                    307:       if (addreg1)
                    308:        output_asm_insn ("add %0,-0x4,%0", &addreg0);
                    309: 
                    310:       /* Do low-numbered word.  */
                    311:       return singlemove_string (operands);
                    312:     }
1.1.1.3   root      313:   else if (optype0 == REGOP && optype1 != REGOP
1.1.1.6 ! root      314:           && reg_overlap_mentioned_p (operands[0], XEXP (operands[1], 0)))
1.1.1.3   root      315:     {
                    316:       /* Do the late half first.  */
                    317:       output_asm_insn (singlemove_string (latehalf), latehalf);
                    318:       /* Then clobber.  */
                    319:       return singlemove_string (operands);
                    320:     }
1.1       root      321: 
                    322:   /* Normal case: do the two words, low-numbered first.  */
                    323: 
                    324:   output_asm_insn (singlemove_string (operands), operands);
                    325: 
                    326:   /* Make any unoffsetable addresses point at high-numbered word.  */
                    327:   if (addreg0)
                    328:     output_asm_insn ("add %0,0x4,%0", &addreg0);
                    329:   if (addreg1)
                    330:     output_asm_insn ("add %0,0x4,%0", &addreg1);
                    331: 
                    332:   /* Do that word.  */
                    333:   output_asm_insn (singlemove_string (latehalf), latehalf);
                    334: 
                    335:   /* Undo the adds we just did.  */
                    336:   if (addreg0)
                    337:     output_asm_insn ("add %0,-0x4,%0", &addreg0);
                    338:   if (addreg1)
                    339:     output_asm_insn ("add %0,-0x4,%0", &addreg1);
                    340: 
                    341:   return "";
                    342: }
                    343: 
                    344: static char *
                    345: output_fp_move_double (operands)
                    346:      rtx *operands;
                    347: {
                    348:   if (FP_REG_P (operands[0]))
                    349:     {
                    350:       if (FP_REG_P (operands[1]))
                    351:        {
                    352:          output_asm_insn ("fmovs %1,%0", operands);
                    353:          operands[0] = gen_rtx (REG, VOIDmode, REGNO (operands[0]) + 1);
                    354:          operands[1] = gen_rtx (REG, VOIDmode, REGNO (operands[1]) + 1);
                    355:          return "fmovs %1,%0";
                    356:        }
                    357:       if (GET_CODE (operands[1]) == REG)
                    358:        {
1.1.1.3   root      359:          if ((REGNO (operands[1]) & 1) == 0)
                    360:            return "std %1,[%%fp-8]\n\tldd [%%fp-8],%0";
                    361:          else
                    362:            {
                    363:              rtx xoperands[3];
                    364:              xoperands[0] = operands[0];
                    365:              xoperands[1] = operands[1];
                    366:              xoperands[2] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
                    367:              output_asm_insn ("st %2,[%%fp-4]\n\tst %1,[%%fp-8]\n\tldd [%%fp-8],%0", xoperands);
                    368:              return "";
                    369:            }
1.1       root      370:        }
1.1.1.4   root      371:       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
                    372:          && (XEXP (XEXP (operands[1], 0), 0) == frame_pointer_rtx
                    373:              || XEXP (XEXP (operands[1], 0), 0) == stack_pointer_rtx)
                    374:          && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == CONST_INT
                    375:          && (INTVAL (XEXP (XEXP (operands[1], 0), 1)) & 0x7) != 0)
                    376:        {
                    377:          rtx xoperands[2];
                    378:          output_asm_insn ("ld %1,%0", operands);
                    379:          xoperands[0] = gen_rtx (REG, GET_MODE (operands[0]),
                    380:                                  REGNO (operands[0]) + 1);
                    381:          xoperands[1] = gen_rtx (MEM, GET_MODE (operands[1]),
                    382:                                  plus_constant (XEXP (operands[1], 0), 4));
                    383:          output_asm_insn ("ld %1,%0", xoperands);
                    384:          return "";
                    385:        }
1.1       root      386:       return "ldd %1,%0";
                    387:     }
                    388:   else if (FP_REG_P (operands[1]))
                    389:     {
                    390:       if (GET_CODE (operands[0]) == REG)
                    391:        {
1.1.1.3   root      392:          if ((REGNO (operands[0]) & 1) == 0)
                    393:            return "std %1,[%%fp-8]\n\tldd [%%fp-8],%0";
                    394:          else
                    395:            {
                    396:              rtx xoperands[3];
                    397:              xoperands[2] = operands[1];
                    398:              xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
                    399:              xoperands[0] = operands[0];
                    400:              output_asm_insn ("std %2,[%%fp-8]\n\tld [%%fp-4],%1\n\tld [%%fp-8],%0", xoperands);
                    401:              return "";
                    402:            }
1.1       root      403:        }
1.1.1.4   root      404:       if (GET_CODE (XEXP (operands[0], 0)) == PLUS
                    405:          && (XEXP (XEXP (operands[0], 0), 0) == frame_pointer_rtx
                    406:              || XEXP (XEXP (operands[0], 0), 0) == stack_pointer_rtx)
                    407:          && GET_CODE (XEXP (XEXP (operands[0], 0), 1)) == CONST_INT
                    408:          && (INTVAL (XEXP (XEXP (operands[0], 0), 1)) & 0x7) != 0)
                    409:        {
                    410:          rtx xoperands[2];
                    411:          output_asm_insn ("st %1,%0", operands);
                    412:          xoperands[1] = gen_rtx (REG, GET_MODE (operands[1]),
                    413:                                  REGNO (operands[1]) + 1);
                    414:          xoperands[0] = gen_rtx (MEM, GET_MODE (operands[0]),
                    415:                                  plus_constant (XEXP (operands[0], 0), 4));
                    416:          output_asm_insn ("st %1,%0", xoperands);
                    417:          return "";
                    418:        }
1.1       root      419:       return "std %1,%0";
                    420:     }
1.1.1.3   root      421:   else abort ();
1.1       root      422: }
                    423: 
                    424: /* Return a REG that occurs in ADDR with coefficient 1.
                    425:    ADDR can be effectively incremented by incrementing REG.  */
                    426: 
                    427: static rtx
                    428: find_addr_reg (addr)
                    429:      rtx addr;
                    430: {
                    431:   while (GET_CODE (addr) == PLUS)
                    432:     {
                    433:       if (GET_CODE (XEXP (addr, 0)) == REG)
                    434:        addr = XEXP (addr, 0);
                    435:       if (GET_CODE (XEXP (addr, 1)) == REG)
                    436:        addr = XEXP (addr, 1);
                    437:       if (CONSTANT_P (XEXP (addr, 0)))
                    438:        addr = XEXP (addr, 1);
                    439:       if (CONSTANT_P (XEXP (addr, 1)))
                    440:        addr = XEXP (addr, 0);
                    441:     }
                    442:   if (GET_CODE (addr) == REG)
                    443:     return addr;
                    444:   return 0;
                    445: }
                    446: 
                    447: /* Load the address specified by OPERANDS[3] into the register
                    448:    specified by OPERANDS[0].
                    449: 
                    450:    OPERANDS[3] may be the result of a sum, hence it could either be:
                    451: 
                    452:    (1) CONST
                    453:    (2) REG
                    454:    (2) REG + CONST_INT
                    455:    (3) REG + REG + CONST_INT
                    456: 
1.1.1.5   root      457:    Note that (3) is not a legitimate address.
1.1       root      458:    All cases are handled here.  */
                    459: 
                    460: void
                    461: output_load_address (operands)
                    462:      rtx *operands;
                    463: {
                    464:   rtx base, offset;
                    465: 
                    466:   if (CONSTANT_P (operands[3]))
                    467:     {
                    468:       output_asm_insn ("set %3,%0", operands);
                    469:       return;
                    470:     }
                    471: 
                    472:   if (REG_P (operands[3]))
                    473:     {
                    474:       if (REGNO (operands[0]) != REGNO (operands[3]))
                    475:        output_asm_insn ("mov %3,%0", operands);
                    476:       return;
                    477:     }
                    478: 
                    479:   base = XEXP (operands[3], 0);
                    480:   offset = XEXP (operands[3], 1);
                    481: 
                    482:   if (GET_CODE (base) == CONST_INT)
                    483:     {
                    484:       rtx tmp = base;
                    485:       base = offset;
                    486:       offset = tmp;
                    487:     }
                    488: 
                    489:   if (GET_CODE (offset) != CONST_INT)
                    490:     abort ();
                    491: 
                    492:   if (REG_P (base))
                    493:     {
                    494:       operands[6] = base;
                    495:       operands[7] = offset;
                    496:       if (SMALL_INT (offset))
                    497:        output_asm_insn ("add %6,%7,%0", operands);
                    498:       else
                    499:        output_asm_insn ("set %7,%0\n\tadd %0,%6,%0", operands);
                    500:     }
                    501:   else
                    502:     {
                    503:       operands[6] = XEXP (base, 0);
                    504:       operands[7] = XEXP (base, 1);
                    505:       operands[8] = offset;
                    506: 
                    507:       if (SMALL_INT (offset))
                    508:        output_asm_insn ("add %6,%7,%0\n\tadd %0,%8,%0", operands);
                    509:       else
                    510:        output_asm_insn ("set %8,%0\n\tadd %0,%6,%0\n\tadd %0,%7,%0", operands);
                    511:     }
                    512: }
                    513: 
1.1.1.5   root      514: /* Output code to place a size count SIZE in register REG.
                    515:    If SIZE is round, then assume that we can use alignment
                    516:    based on that roundness, and return an integer saying
                    517:    what alignment (roundness, transfer size) we will be using.
                    518: 
                    519:    Because block moves are pipelined, we don't include the
                    520:    first element in the transfer of SIZE to REG.  */
                    521: 
                    522: static int
                    523: output_size_for_block_move (size, reg)
                    524:      rtx size, reg;
                    525: {
                    526:   int align;
                    527:   rtx xoperands[2];
                    528:   xoperands[0] = reg;
                    529: 
                    530:   /* First, figure out best alignment we may assume.  */
                    531:   if (REG_P (size))
                    532:     {
                    533:       xoperands[1] = size;
                    534:       output_asm_insn ("sub %1,1,%0", xoperands);
                    535:       align = 1;
                    536:     }
                    537:   else
                    538:     {
                    539:       int i = INTVAL (size);
                    540: 
                    541:       if (i & 1)
                    542:        align = 1;
                    543:       else if (i & 3)
                    544:        align = 2;
                    545:       else
                    546:        align = 4;
                    547: 
                    548:       /* predecrement count.  */
                    549:       i -= align;
                    550:       if (i < 0) abort ();
                    551: 
                    552:       xoperands[1] = gen_rtx (CONST_INT, VOIDmode, i);
                    553: 
                    554:       output_asm_insn ("set %1,%0", xoperands);
                    555:     }
                    556:   return align;
                    557: }
                    558: 
                    559: /* Emit code to perform a block move.
                    560: 
                    561:    OPERANDS[0] is the destination.
                    562:    OPERANDS[1] is the source.
                    563:    OPERANDS[2] is the size.
                    564: 
                    565:    We clobber registers 8,9,10, and register 1 (which we
                    566:    do not need to worry about) during this move.
                    567: 
                    568:    It may happen that registers 8,9, and/or 10 are live
                    569:    up to this call, in which case we must be careful
                    570:    to use their values before clobbering them.
                    571: 
                    572:    This function attempts to take advantage of natural
                    573:    luck, such as an operand which is already in an operand
                    574:    register, and hence does not need to be moved around.
                    575: 
                    576:    Perhaps some day, GNU CC will be able to handle dynamic register
                    577:    allocation to such inline library calls.
                    578:    [No, never, because there is already provision for handling
                    579:    library calls at RTL generation time, and I have no interest
                    580:    in maintaining a redundant mechanism for them.
                    581:    I hope some day the movstrsi pattern
                    582:    for sparc will be deleted and an ordinary library call will be
                    583:    used instead.  Then this function will be unnecessary. - rms]  */
                    584: 
                    585: #define COMPATIBLE(REG,OP) \
                    586:   (reg_conflicts[REG].ops[0] == operands[OP]   \
                    587:    && (op_conflicts[OP].n_regs == 0            \
                    588:        || (op_conflicts[OP].n_regs == 1                \
                    589:           && op_conflicts[OP].regs[0] == REG)))
                    590: 
1.1       root      591: char *
                    592: output_block_move (operands)
                    593:      rtx *operands;
                    594: {
1.1.1.5   root      595:   /* A vector for our computed operands.  Note that load_output_address
                    596:      makes use of up to the 8th element of this vector.  */
                    597:   rtx xoperands[10];
1.1       root      598:   static int movstrsi_label = 0;
1.1.1.5   root      599:   int align = -1;              /* not yet known */
1.1       root      600:   int i, j;
                    601: 
1.1.1.5   root      602:   /* For each of registers 8, 9, and 10, keep track of
                    603:      which operands use them.  */
                    604:   struct
                    605:     {
                    606:       int n_ops;
                    607:       rtx ops[3];
                    608:     } reg_conflicts[3];
                    609: 
                    610:   /* For each of the 3 operands, keep track of which registers
                    611:      they use.  Each operand can only use 2 registers.  */
                    612:   struct
                    613:     {
                    614:       int n_regs;
                    615:       char regs[2];
                    616:     } op_conflicts[3];
                    617: 
                    618:   /* Make rtxs for the register operands we are using, and
                    619:      initialize all data structures.  */
                    620:   rtx regs[3];
                    621:   rtx reg8 = gen_rtx (REG, SImode, 8);
                    622:   rtx reg9 = gen_rtx (REG, SImode, 9);
                    623:   rtx reg10 = gen_rtx (REG, SImode, 10);
                    624:   regs[0] = reg8;
                    625:   regs[1] = reg9;
                    626:   regs[2] = reg10;
                    627: 
1.1       root      628:   /* Since we clobber untold things, nix the condition codes.  */
                    629:   CC_STATUS_INIT;
                    630: 
1.1.1.5   root      631:   /* Recognize special cases of block moves.  These occur
                    632:      when GNU C++ is forced to treat something as BLKmode
                    633:      to keep it in memory, when its mode could be represented
                    634:      with something smaller.  */
                    635:   if (GET_CODE (operands[2]) == CONST_INT
                    636:       && INTVAL (operands[2]) <= 16)
                    637:     {
                    638:       int size = INTVAL (operands[2]);
                    639:       xoperands[0] = XEXP (operands[0], 0);
                    640:       xoperands[1] = XEXP (operands[1], 0);
                    641:       /* If we are lucky, then this rtx can safely have
                    642:         its INTVAL clobbered.  */
                    643:       xoperands[2] = gen_rtx (CONST_INT, VOIDmode, 13);
                    644: 
                    645:       if (size & 1)
                    646:        {
                    647:          if (memory_address_p (QImode, plus_constant (xoperands[0], size))
                    648:              && memory_address_p (QImode, plus_constant (xoperands[1], size)))
                    649:            {
                    650:              for (i = size-1; i >= 0; i--)
                    651:                {
                    652:                  INTVAL (xoperands[2]) = i;
                    653:                  output_asm_insn ("ldub [%a1+%2],%%g1\n\tstb %%g1,[%a0+%2]",
                    654:                                   xoperands);
                    655:                }
                    656:              return "";
                    657:            }
                    658:        }
                    659:       else if (size & 2)
                    660:        {
                    661:          if (memory_address_p (HImode, plus_constant (xoperands[0], size))
                    662:              && memory_address_p (HImode, plus_constant (xoperands[1], size)))
                    663:            {
                    664:              for (i = (size>>1)-1; i >= 0; i--)
                    665:                {
                    666:                  INTVAL (xoperands[2]) = i<<1;
                    667:                  output_asm_insn ("lduh [%a1+%2],%%g1\n\tsth %%g1,[%a0+%2]",
                    668:                                   xoperands);
                    669:                }
                    670:              return "";
                    671:            }
                    672:        }
                    673:       else
                    674:        {
                    675:          if (memory_address_p (SImode, plus_constant (xoperands[0], size))
                    676:              && memory_address_p (SImode, plus_constant (xoperands[1], size)))
                    677:            {
                    678:              for (i = (size>>2)-1; i >= 0; i--)
                    679:                {
                    680:                  INTVAL (xoperands[2]) = i<<2;
                    681:                  output_asm_insn ("ld [%a1+%2],%%g1\n\tst %%g1,[%a0+%2]",
                    682:                                   xoperands);
                    683:                }
                    684:              return "";
                    685:            }
                    686:        }
                    687:     }
                    688: 
                    689:   bzero (reg_conflicts, sizeof (reg_conflicts));
                    690:   bzero (op_conflicts, sizeof (op_conflicts));
1.1.1.6 ! root      691:   xoperands[0] = 0;
        !           692:   xoperands[1] = 0;
        !           693:   xoperands[2] = 0;
1.1.1.5   root      694: 
1.1       root      695:   /* Get past the MEMs.  */
                    696:   operands[0] = XEXP (operands[0], 0);
                    697:   operands[1] = XEXP (operands[1], 0);
                    698: 
1.1.1.5   root      699:   /* See which operands use which registers.  */
                    700:   for (i = 0; i < 3; i++)
1.1       root      701:     {
1.1.1.5   root      702:       for (j = 0; j < 3; j++)
                    703:        {
1.1.1.6 ! root      704:          if (reg_overlap_mentioned_p (regs[i], operands[j]))
1.1.1.5   root      705:            {
                    706:              reg_conflicts[i].ops[reg_conflicts[i].n_ops++] = operands[j];
                    707:              op_conflicts[j].regs[op_conflicts[j].n_regs++] = i;
                    708:            }
                    709:        }
1.1       root      710:     }
1.1.1.5   root      711: 
                    712:   /* We need to know the alignment in order to set up
                    713:      the destination address for a pipelined move.
                    714:      Set it up first, if that is at all easy to do.  */
                    715:   if (op_conflicts[2].n_regs == 0
                    716:       || (op_conflicts[2].n_regs == 1
                    717:          && (reg_conflicts[op_conflicts[2].regs[0]].n_ops == 0
                    718:              || (reg_conflicts[op_conflicts[2].regs[0]].n_ops == 1
                    719:                  && (reg_conflicts[op_conflicts[2].regs[0]].ops[0]
                    720:                      == operands[2])))))
                    721:     {
                    722:       /* This is the size of the transfer.
                    723:          Either use the register which already contains the size,
                    724:         or use a free register (used by no operands).  */
                    725:       rtx reg = op_conflicts[2].n_regs == 1
                    726:        ? regs[op_conflicts[2].regs[0]]
                    727:          : reg_conflicts[0].n_ops == 0
                    728:            ? regs[0]
                    729:              : reg_conflicts[1].n_ops == 0
                    730:                ? regs[1] : regs[2];
                    731: 
                    732:       align = output_size_for_block_move (operands[2], reg);
                    733: 
                    734:       /* Mark this registers as being unavailable.  */
                    735:       reg_conflicts[REGNO (reg) - 8].n_ops = -1;
                    736: 
                    737:       /* Update register usage information for the size operand.  */
                    738:       op_conflicts[2].n_regs = 0;
                    739:       xoperands[2] = reg;
                    740:     }
                    741:      
                    742:   /* If register is used by only one operand,
                    743:      make that register the home for that operand.  */
1.1       root      744:   for (i = 0; i < 3; i++)
                    745:     {
1.1.1.5   root      746:       if (reg_conflicts[i].n_ops == 0)
1.1       root      747:        {
1.1.1.5   root      748:          /* No conflicts for this register.  We can
                    749:             immediately load it with an operand.  Try
                    750:             size first, then source, last dest.  */
                    751:          if (xoperands[2] == 0)
                    752:            {
                    753:              j = 2;
                    754:              /* This is the size of the transfer.  */
                    755:              align = output_size_for_block_move (operands[2], regs[i]);
                    756:              xoperands[2] = regs[i];
                    757:            }
                    758:          else if (xoperands[1] == 0)
                    759:            {
                    760:              /* The source.  */
                    761:              j = 1;
                    762:              xoperands[1] = regs[i];
                    763:              xoperands[4] = operands[1];
                    764:              output_load_address (xoperands + 1);
                    765:            }
                    766:          else
                    767:            {
                    768:              /* The destination.  */
                    769:              j = 0;
                    770:              xoperands[0] = regs[i];
                    771:              xoperands[3] = plus_constant (operands[0], align);
                    772:              output_load_address (xoperands);
                    773:            }
                    774:          /* Mark this register as now unavailable.  */
                    775:          reg_conflicts[i].n_ops = -1;
1.1       root      776:        }
1.1.1.5   root      777:       else if (reg_conflicts[i].n_ops == 1)
1.1       root      778:        {
1.1.1.5   root      779:          /* One conflict.  If the conflict is one which
                    780:             does not clobber anything which depends on this
                    781:             register, go ahead and load the operand
                    782:             into this register.  */
                    783:          if (COMPATIBLE (i, 2))
                    784:            {
                    785:              j = 2;
                    786:              /* This is the size of the transfer.  */
                    787:              align = output_size_for_block_move (operands[2], regs[i]);
                    788:              xoperands[2] = regs[i];
                    789:            }
                    790:          else
                    791:            {
                    792:              /* An address for the transfer.
                    793:                 Set up for pipelined operation: dest must contain
                    794:                 a pre-incremented address, because its index is
                    795:                 pre-decremented.  */
                    796: 
                    797:              if (COMPATIBLE (i, 0))
                    798:                {
                    799:                  /* The destination.  */
                    800:                  if (align < 0)
                    801:                    continue;
                    802:                  j = 0;
                    803:                  xoperands[0] = regs[i];
                    804:                  xoperands[3] = plus_constant (operands[0], align);
                    805:                  output_load_address (xoperands);
                    806:                }
                    807:              else if (COMPATIBLE (i, 1))
                    808:                {
                    809:                  /* The source.  */
                    810:                  j = 1;
                    811:                  xoperands[1] = regs[i];
                    812:                  xoperands[4] = operands[1];
                    813:                  output_load_address (xoperands + 1);
                    814:                }
                    815:              else continue;
                    816:            }
                    817:          /* Mark this register as now unavailable.  */
                    818:          reg_conflicts[i].n_ops = -1;
                    819: 
                    820:          /* Update register usage information for operands.  */
                    821:          op_conflicts[j].n_regs--;
                    822:          if (op_conflicts[j].n_regs && op_conflicts[j].regs[0] == i)
                    823:            op_conflicts[j].regs[0] = op_conflicts[j].regs[1];
1.1       root      824:        }
                    825:     }
                    826: 
1.1.1.5   root      827:   if (xoperands[0] == 0 || xoperands[1] == 0 || xoperands[2] == 0)
1.1       root      828:     {
1.1.1.5   root      829:       /* There were interlocking register requirements.  First
                    830:         user to submit code which triggered that wins a prize.  */
                    831:       abort ();
1.1       root      832:     }
                    833: 
                    834:   xoperands[3] = gen_rtx (CONST_INT, VOIDmode, movstrsi_label++);
                    835:   xoperands[4] = gen_rtx (CONST_INT, VOIDmode, align);
                    836: 
1.1.1.5   root      837:   if (align == 1)
                    838:     output_asm_insn ("\nLm%3:\n\tldub [%1+%2],%%g1\n\tsubcc %2,%4,%2\n\tbge Lm%3\n\tstb %%g1,[%0+%2]", xoperands);
                    839:   else if (align == 2)
                    840:     output_asm_insn ("\nLm%3:\n\tlduh [%1+%2],%%g1\n\tsubcc %2,%4,%2\n\tbge Lm%3\n\tsth %%g1,[%0+%2]", xoperands);
                    841:   else
                    842:     output_asm_insn ("\nLm%3:\n\tld [%1+%2],%%g1\n\tsubcc %2,%4,%2\n\tbge Lm%3\n\tst %%g1,[%0+%2]", xoperands);
1.1       root      843:   return "";
                    844: }
1.1.1.5   root      845: 
                    846: /* What the sparc lacks in hardware, make up for in software.
                    847:    Compute a fairly good sequence of shift and add insns
                    848:    to make a multiply happen.  */
1.1       root      849: 
                    850: #define ABS(x) ((x) < 0 ? -(x) : x)
                    851: 
                    852: char *
                    853: output_mul_by_constant (insn, operands, unsignedp)
                    854:      rtx insn;
                    855:      rtx *operands;
                    856:      int unsignedp;
                    857: {
                    858:   int c;                       /* Size of constant */
                    859:   int shifts[BITS_PER_WORD];   /* Table of shifts */
1.1.1.4   root      860:   unsigned int p, log;         /* A power of two, and its log */
1.1       root      861:   int d1, d2;                  /* Differences of c and p */
                    862:   int first = 1;               /* True if dst has unknown data in it */
                    863:   int i;
                    864: 
                    865:   c = INTVAL (operands[2]);
                    866:   if (c == 0)
                    867:     {
                    868:       /* should not happen.  */
                    869:       abort ();
                    870:       if (GET_CODE (operands[0]) == MEM)
                    871:        return "st %%g0,%0";
                    872:       return "mov %%g0,%0";
                    873:     }
                    874: 
                    875:   output_asm_insn ("! start open coded multiply");
                    876: 
                    877:   /* Clear out the table of shifts. */
                    878:   for (i = 0; i < BITS_PER_WORD; ++i)
                    879:     shifts[i] = 0;
                    880: 
                    881:   while (c)
                    882:     {
                    883:       /* Find the power of two nearest ABS(c) */
                    884:       p = 1, log = 0;
                    885:       do
                    886:        {
                    887:          d1 = ABS(c) - p;
                    888:          p *= 2;
                    889:          ++log;
                    890:        }
                    891:       while (p < ABS(c));
                    892:       d2 = p - ABS(c);
                    893: 
                    894:       /* Make an appropriate entry in shifts for p. */
                    895:       if (d2 < d1)
                    896:        {
                    897:          shifts[log] = c < 0 ? -1 : 1;
                    898:          c = c < 0 ? d2 : -d2;
                    899:        }
                    900:       else
                    901:        {
                    902:          shifts[log - 1] = c < 0 ? -1 : 1;
                    903:          c = c < 0 ? -d1 : d1;
                    904:        }
                    905:     }
                    906: 
                    907:   /* Take care of the first insn in sequence.
                    908:      We know we have at least one. */
                    909: 
                    910:   /* A value of -1 in shifts says to subtract that power of two, and a value
                    911:      of 1 says to add that power of two. */
                    912:   for (i = 0; ; i++)
                    913:     if (shifts[i])
                    914:       {
                    915:        if (i)
                    916:          {
                    917:            operands[2] = gen_rtx (CONST_INT, VOIDmode, i);
1.1.1.5   root      918:            output_asm_insn ("sll %1,%2,%%g1", operands);
1.1       root      919:          }
1.1.1.5   root      920:        else output_asm_insn ("mov %1,%%g1", operands);
1.1       root      921: 
                    922:        log = i;
                    923:        if (shifts[i] < 0)
1.1.1.5   root      924:          output_asm_insn ("sub %%g0,%%g1,%0", operands);
1.1       root      925:        else
1.1.1.5   root      926:          output_asm_insn ("mov %%g1,%0", operands);
1.1       root      927:        break;
                    928:       }
                    929: 
                    930:   /* A value of -1 in shifts says to subtract that power of two, and a value
                    931:      of 1 says to add that power of two--continued.  */
                    932:   for (i += 1; i < BITS_PER_WORD; ++i)
                    933:     if (shifts[i])
                    934:       {
                    935:        if (i - log > 0)
                    936:          {
                    937:            operands[2] = gen_rtx (CONST_INT, VOIDmode, i - log);
1.1.1.5   root      938:            output_asm_insn ("sll %%g1,%2,%%g1", operands);
1.1       root      939:          }
                    940:        else
                    941:          {
                    942:            operands[2] = gen_rtx (CONST_INT, VOIDmode, log - i);
1.1.1.5   root      943:            output_asm_insn ("sra %%g1,%2,%%g1", operands);
1.1       root      944:          }
                    945:        log = i;
                    946:        if (shifts[i] < 0)
1.1.1.5   root      947:          output_asm_insn ("sub %0,%%g1,%0", operands);
1.1       root      948:        else
1.1.1.5   root      949:          output_asm_insn ("add %0,%%g1,%0", operands);
1.1       root      950:       }
                    951: 
                    952:   output_asm_insn ("! end open coded multiply");
                    953: 
                    954:   return "";
                    955: }
                    956: 
                    957: char *
                    958: output_mul_insn (operands, unsignedp)
                    959:      rtx *operands;
                    960:      int unsignedp;
                    961: {
                    962:   int lucky1 = ((unsigned)REGNO (operands[1]) - 8) <= 1;
                    963:   int lucky2 = ((unsigned)REGNO (operands[2]) - 8) <= 1;
                    964: 
                    965:   if (lucky1)
                    966:     if (lucky2)
                    967:       output_asm_insn ("call .mul,2\n\tnop", operands);
                    968:     else
                    969:       {
                    970:        rtx xoperands[2];
                    971:        xoperands[0] = gen_rtx (REG, SImode,
                    972:                                8 ^ (REGNO (operands[1]) == 8));
                    973:        xoperands[1] = operands[2];
                    974:        output_asm_insn ("call .mul,2\n\tmov %1,%0", xoperands);
                    975:       }
                    976:   else if (lucky2)
                    977:     {
                    978:       rtx xoperands[2];
                    979:       xoperands[0] = gen_rtx (REG, SImode,
                    980:                              8 ^ (REGNO (operands[2]) == 8));
                    981:       xoperands[1] = operands[1];
                    982:       output_asm_insn ("call .mul,2\n\tmov %1,%0", xoperands);
                    983:     }
                    984:   else
                    985:     {
                    986:       output_asm_insn ("mov %1,%%o0\n\tcall .mul,2\n\tmov %2,%%o1",
                    987:                       operands);
                    988:     }
                    989: 
                    990:   if (REGNO (operands[0]) == 8)
                    991:     return "";
                    992:   return "mov %%o0,%0";
                    993: }
                    994: 
                    995: /* Make floating point register f0 contain 0.
                    996:    SIZE is the number of registers (including f0)
                    997:    which should contain 0.  */
                    998: 
                    999: void
                   1000: make_f0_contain_0 (size)
                   1001:      int size;
                   1002: {
                   1003:   if (size == 1)
1.1.1.3   root     1004:     output_asm_insn ("ld [%%fp-16],%%f0", 0);
1.1       root     1005:   else if (size == 2)
1.1.1.3   root     1006:     output_asm_insn ("ldd [%%fp-16],%%f0", 0);
1.1       root     1007: }
1.1.1.4   root     1008: 
                   1009: /* Output reasonable peephole for set-on-condition-code insns.
                   1010:    Note that these insns assume a particular way of defining
                   1011:    labels.  Therefore, *both* tm-sparc.h and this function must
                   1012:    be changed if a new syntax is needed.  */
                   1013: 
                   1014: char *
                   1015: output_scc_insn (code, operands)
                   1016:      enum rtx_code code;
                   1017:      rtx *operands;
                   1018: {
                   1019:   rtx xoperands[2];
                   1020:   rtx label = gen_label_rtx ();
                   1021: 
                   1022:   xoperands[0] = operands[0];
                   1023:   xoperands[1] = label;
                   1024: 
                   1025:   switch (code)
                   1026:     {
                   1027:     case NE:
                   1028:       if (cc_status.flags & CC_IN_FCCR)
1.1.1.5   root     1029:        output_asm_insn ("fbne,a %l0", &label);
1.1.1.4   root     1030:       else
1.1.1.5   root     1031:        output_asm_insn ("bne,a %l0", &label);
1.1.1.4   root     1032:       break;
                   1033:     case EQ:
                   1034:       if (cc_status.flags & CC_IN_FCCR)
1.1.1.5   root     1035:        output_asm_insn ("fbe,a %l0", &label);
1.1.1.4   root     1036:       else
1.1.1.5   root     1037:        output_asm_insn ("be,a %l0", &label);
1.1.1.4   root     1038:       break;
                   1039:     case GE:
                   1040:       if (cc_status.flags & CC_IN_FCCR)
1.1.1.5   root     1041:        output_asm_insn ("fbge,a %l0", &label);
1.1.1.4   root     1042:       else
1.1.1.5   root     1043:        output_asm_insn ("bge,a %l0", &label);
1.1.1.4   root     1044:       break;
                   1045:     case GT:
                   1046:       if (cc_status.flags & CC_IN_FCCR)
1.1.1.5   root     1047:        output_asm_insn ("fbg,a %l0", &label);
1.1.1.4   root     1048:       else
1.1.1.5   root     1049:        output_asm_insn ("bg,a %l0", &label);
1.1.1.4   root     1050:       break;
                   1051:     case LE:
                   1052:       if (cc_status.flags & CC_IN_FCCR)
1.1.1.5   root     1053:        output_asm_insn ("fble,a %l0", &label);
1.1.1.4   root     1054:       else
1.1.1.5   root     1055:        output_asm_insn ("ble,a %l0", &label);
1.1.1.4   root     1056:       break;
                   1057:     case LT:
                   1058:       if (cc_status.flags & CC_IN_FCCR)
1.1.1.5   root     1059:        output_asm_insn ("fbl,a %l0", &label);
1.1.1.4   root     1060:       else
1.1.1.5   root     1061:        output_asm_insn ("bl,a %l0", &label);
1.1.1.4   root     1062:       break;
                   1063:     case GEU:
                   1064:       if (cc_status.flags & CC_IN_FCCR)
                   1065:        abort ();
                   1066:       else
1.1.1.5   root     1067:        output_asm_insn ("bgeu,a %l0", &label);
1.1.1.4   root     1068:       break;
                   1069:     case GTU:
                   1070:       if (cc_status.flags & CC_IN_FCCR)
                   1071:        abort ();
                   1072:       else
1.1.1.5   root     1073:        output_asm_insn ("bgu,a %l0", &label);
1.1.1.4   root     1074:       break;
                   1075:     case LEU:
                   1076:       if (cc_status.flags & CC_IN_FCCR)
                   1077:        abort ();
                   1078:       else
1.1.1.5   root     1079:        output_asm_insn ("bleu,a %l0", &label);
1.1.1.4   root     1080:       break;
                   1081:     case LTU:
                   1082:       if (cc_status.flags & CC_IN_FCCR)
                   1083:        abort ();
                   1084:       else
1.1.1.5   root     1085:        output_asm_insn ("blu,a %l0", &label);
1.1.1.4   root     1086:       break;
                   1087:     default:
                   1088:       abort ();
                   1089:     }
1.1.1.5   root     1090:   output_asm_insn ("mov 1,%0\n\tmov 0,%0\n%l1", xoperands);
1.1.1.4   root     1091:   return "";
                   1092: }
                   1093: 
1.1.1.5   root     1094: /* Output a delayed branch insn with the delay insn in its
                   1095:    branch slot.  The delayed branch insn template is in TEMPLATE,
                   1096:    with operands OPERANDS.  The insn in its delay slot is INSN.  */
1.1.1.4   root     1097: 
                   1098: char *
                   1099: output_delay_insn (template, operands, insn)
                   1100:      char *template;
                   1101:      rtx *operands;
                   1102:      rtx insn;
                   1103: {
                   1104:   extern char *insn_template[];
                   1105:   extern char *(*insn_outfun[])();
                   1106:   rtx pat = gen_rtx (SET, VOIDmode,
                   1107:                     XVECEXP (PATTERN (insn), 0, 0),
                   1108:                     XVECEXP (PATTERN (insn), 0, 1));
                   1109:   rtx delay_insn = gen_rtx (INSN, VOIDmode, 0, 0, 0, pat, -1, 0, 0);
                   1110:   int insn_code_number;
                   1111: 
                   1112:   /* Output the branch instruction first.  */
                   1113:   output_asm_insn (template, operands);
                   1114: 
                   1115:   /* Now recognize the insn which we put in its delay slot.
                   1116:      We must do this after outputing the branch insn,
                   1117:      since operands may just be a pointer to `recog_operands'.  */
                   1118:   insn_code_number = recog (pat, delay_insn);
                   1119:   if (insn_code_number == -1)
                   1120:     abort ();
                   1121: 
                   1122:   /* Now get the template for what this insn would
                   1123:      have been, without the branch.  Its operands are
                   1124:      exactly the same as they would be, so we don't
                   1125:      need to do an insn_extract.  */
                   1126:   template = insn_template[insn_code_number];
                   1127:   if (template == 0)
                   1128:     template = (*insn_outfun[insn_code_number]) (operands, delay_insn);
                   1129:   output_asm_insn (template, operands);
                   1130:   return "";
                   1131: }

unix.superglobalmegacorp.com

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