home *** CD-ROM | disk | FTP | other *** search
/ Education Sampler 1992 [NeXTSTEP] / Education_1992_Sampler.iso / NeXT / GnuSource / cplusplus-8 / config / out-sparc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-12-12  |  55.5 KB  |  2,072 lines

  1. /* Subroutines for insn-output.c for Sun SPARC.
  2.    Copyright (C) 1987, 1988, 1989 Free Software Foundation, Inc.
  3.    Contributed by Michael Tiemann (tiemann@mcc.com)
  4.  
  5. This file is part of GNU CC.
  6.  
  7. GNU CC is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 1, or (at your option)
  10. any later version.
  11.  
  12. GNU CC is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with GNU CC; see the file COPYING.  If not, write to
  19. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  20.  
  21. /* Global variables for machine-dependend things.  */
  22.  
  23. /* This should go away if we pass floats to regs via
  24.    the stack instead of the frame, and if we learn how
  25.    to renumber all the registers when we don't do a save (hard!).  */
  26. extern int frame_pointer_needed;
  27.  
  28. static rtx find_addr_reg ();
  29.  
  30. rtx next_real_insn_no_labels ();
  31.  
  32. /* Return non-zero only if OP is a register of mode MODE,
  33.    or const0_rtx.  */
  34. int
  35. reg_or_0_operand (op, mode)
  36.      rtx op;
  37.      enum machine_mode mode;
  38. {
  39.   return (op == const0_rtx || register_operand (op, mode));
  40. }
  41.  
  42. /* Return non-zero if INSN is a conditional insn with a predicate
  43.    valid after an addcc or subcc instruction.  */
  44.  
  45. int
  46. ignore_overflow_conditional_p (insn)
  47.      rtx insn;
  48. {
  49.   rtx x = SET_SRC (PATTERN (insn));
  50.   RTX_CODE code;
  51.   if (GET_CODE (x) == IF_THEN_ELSE)
  52.     x = XEXP (x, 0);
  53.   code = GET_CODE (x);
  54.   return code == EQ || code == NE || code == GE || code == LT;
  55. }
  56.  
  57. /* Return non-zero if this pattern, can be evaluated safely, even if it
  58.    was not asked for.  */
  59. int
  60. safe_insn_src_p (op, mode)
  61.      rtx op;
  62.      enum machine_mode mode;
  63. {
  64.   /* Just experimenting.  */
  65.  
  66.   /* No floating point src is safe if it contains an arithmetic
  67.      operation, since that operation may trap.  */
  68.   switch (GET_CODE (op))
  69.     {
  70.     case CONST_INT:
  71.     case LABEL_REF:
  72.     case SYMBOL_REF:
  73.     case CONST:
  74.       return 1;
  75.  
  76.     case REG:
  77.       return 1;
  78.  
  79.     case MEM:
  80.       return CONSTANT_ADDRESS_P (XEXP (op, 0));
  81.  
  82.       /* We never need to negate or complement constants.  */
  83.     case NEG:
  84.       return (mode != SFmode && mode != DFmode);
  85.     case NOT:
  86.       return 1;
  87.  
  88.     case COMPARE:
  89.     case MINUS:
  90.     case PLUS:
  91.       return (mode != SFmode && mode != DFmode);
  92.     case AND:
  93.     case IOR:
  94.     case XOR:
  95.     case LSHIFT:
  96.     case ASHIFT:
  97.     case ASHIFTRT:
  98.     case LSHIFTRT:
  99.       if ((GET_CODE (XEXP (op, 0)) == CONST_INT && ! SMALL_INT (XEXP (op, 0)))
  100.       || (GET_CODE (XEXP (op, 1)) == CONST_INT && ! SMALL_INT (XEXP (op, 1))))
  101.     return 0;
  102.       return 1;
  103.  
  104.     default:
  105.       return 0;
  106.     }
  107. }
  108.  
  109. /* Return 1 if REG is clobbered in IN.
  110.    Return 0 if REG is used in IN (other than being clobbered).
  111.    Return 2 if REG does not appear in IN.  */
  112.  
  113. static int
  114. reg_clobbered_p (reg, in)
  115.      rtx reg;
  116.      rtx in;
  117. {
  118.   register char *fmt;
  119.   register int i, result = 0;
  120.  
  121.   register enum rtx_code code;
  122.  
  123.   if (in == 0)
  124.     return 2;
  125.  
  126.   code = GET_CODE (in);
  127.  
  128.   switch (code)
  129.     {
  130.       /* Let these fail out quickly.  */
  131.     case CONST_INT:
  132.     case SYMBOL_REF:
  133.     case CONST:
  134.       return 2;
  135.  
  136.     case SUBREG:
  137.       if (SUBREG_WORD (in) != 0)
  138.     in = gen_rtx (REG, SImode, REGNO (SUBREG_REG (in)) + SUBREG_WORD (in));
  139.       else
  140.     in = SUBREG_REG (in);
  141.  
  142.     case REG:
  143.       if (in == reg
  144.       || refers_to_regno_p (REGNO (reg),
  145.                 REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
  146.                 in, 0))
  147.     return 0;
  148.       return 2;
  149.  
  150.     case SET:
  151.       if (SET_SRC (in) == reg
  152.       || refers_to_regno_p (REGNO (reg),
  153.                 REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
  154.                 SET_SRC (in), 0))
  155.     return 0;
  156.  
  157.       if (SET_DEST (in) == reg)
  158.     return 1;
  159.  
  160.       if (refers_to_regno_p (REGNO (reg),
  161.                  REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
  162.                  SET_DEST (in), 0))
  163.     if (GET_CODE (SET_DEST (in)) == REG
  164.         || GET_CODE (SET_DEST (in)) == SUBREG)
  165.       return 1;
  166.     else
  167.       return 0;
  168.       return 2;
  169.  
  170.     case USE:
  171.       if (XEXP (in, 0) == reg
  172.       || refers_to_regno_p (REGNO (reg),
  173.                 REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
  174.                 XEXP (in, 0), 0))
  175.     return 0;
  176.       return 2;
  177.  
  178.     case CLOBBER:
  179.       if (XEXP (in, 0) == reg)
  180.     return 1;
  181.       /* If the CLOBBER expression is a SUBREG, accept that as a
  182.      clobber.  But if it is some expression based on this register,
  183.      that is like a USE as far as this register is concerned,
  184.      so we won't take it.  */
  185.       if (refers_to_regno_p (REGNO (reg),
  186.                  REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
  187.                  XEXP (in, 0), 0))
  188.     if (GET_CODE (XEXP (in, 0)) == REG
  189.         || GET_CODE (XEXP (in, 0)) == SUBREG)
  190.       return 1;
  191.     else
  192.       return 0;
  193.       return 2;
  194.     }
  195.  
  196.   fmt = GET_RTX_FORMAT (code);
  197.  
  198.   result = 2;
  199.  
  200.   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
  201.     {
  202.       if (fmt[i] == 'E')
  203.     {
  204.       register int j;
  205.       for (j = XVECLEN (in, i) - 1; j >= 0; j--)
  206.         switch (reg_clobbered_p (reg, XVECEXP (in, i, j)))
  207.           {
  208.           case 0:
  209.         return 0;
  210.           case 2:
  211.         continue;
  212.           case 1:
  213.         result = 1;
  214.         break;
  215.           }
  216.     }
  217.       else if (fmt[i] == 'e')
  218.     switch (reg_clobbered_p (reg, XEXP (in, i)))
  219.       {
  220.       case 0:
  221.         return 0;
  222.       case 2:
  223.         continue;
  224.       case 1:
  225.         result = 1;
  226.         break;
  227.       }
  228.     }
  229.   return result;
  230. }
  231.  
  232. /* Return non-zero if OP can be written to without screwing up
  233.    GCC's model of what's going on.  It is assumed that this operand
  234.    appears in the dest position of a SET insn in a conditional
  235.    branch's delay slot.  AFTER is the label to start looking from.  */
  236. int
  237. operand_clobbered_before_used_after (op, after)
  238.      rtx op;
  239.      rtx after;
  240. {
  241.   extern char call_used_regs[];
  242.  
  243.   /* Just experimenting.  */
  244.   if (GET_CODE (op) == CC0)
  245.     return 1;
  246.   if (GET_CODE (op) == REG)
  247.     {
  248.       rtx insn;
  249.  
  250.       if (op == stack_pointer_rtx)
  251.     return 0;
  252.  
  253.       for (insn = NEXT_INSN (after); insn; insn = NEXT_INSN (insn))
  254.     {
  255.       if (GET_CODE (insn) == NOTE)
  256.         continue;
  257.       if (GET_CODE (insn) == INSN
  258.           || GET_CODE (insn) == JUMP_INSN
  259.           || GET_CODE (insn) == CALL_INSN)
  260.         {
  261.           switch (reg_clobbered_p (op, PATTERN (insn)))
  262.         {
  263.         case 0:
  264.           return 0;
  265.         case 2:
  266.           break;
  267.         case 1:
  268.           return 1;
  269.         }
  270.           if (dead_or_set_p (insn, op))
  271.         return 1;
  272.         }
  273.       else if (GET_CODE (insn) == CODE_LABEL)
  274.         return 0;
  275.       if (GET_CODE (insn) == JUMP_INSN)
  276.         {
  277.           if (condjump_p (insn))
  278.         return 0;
  279.           /* This is a jump insn which has already
  280.          been mangled.  We can't tell what it does.  */
  281.           if (GET_CODE (PATTERN (insn)) == PARALLEL)
  282.         return 0;
  283.           if (! JUMP_LABEL (insn))
  284.         return 0;
  285.           /* Keep following jumps.  */
  286.           insn = JUMP_LABEL (insn);
  287.         }
  288.     }
  289.       return 1;
  290.     }
  291.  
  292.   /* In both of these cases, the first insn executed
  293.      for this op will be a sethi %hi(whatever),%g1,
  294.      which is tolerable.  */
  295.   if (GET_CODE (op) == MEM)
  296.     return (CONSTANT_ADDRESS_P (XEXP (op, 0)));
  297.  
  298.   return 0;
  299. }
  300.  
  301. /* Return non-zero if this pattern, as a source to a "SET",
  302.    is known to yield an instruction of unit size.  */
  303. int
  304. single_insn_src_p (op, mode)
  305.      rtx op;
  306.      enum machine_mode mode;
  307. {
  308.   switch (GET_CODE (op))
  309.     {
  310.     case CONST_INT:
  311. #if 1
  312.       /* This is not always a single insn src, technically,
  313.      but output_delayed_branch knows how to deal with it.  */
  314.       return 1;
  315. #else
  316.       if (SMALL_INT (op))
  317.     return 1;
  318.       /* We can put this set insn into delay slot, because this is one
  319.      insn; 'sethi'.  */
  320.       if ((INTVAL (op) & 0x3ff) == 0)
  321.     return 1;
  322.  
  323.       /* This is not a single insn src, technically,
  324.      but output_delayed_branch knows how to deal with it.  */
  325.       return 1;
  326. #endif
  327.  
  328. #if 1
  329.     case SYMBOL_REF:
  330.       /* This is not a single insn src, technically,
  331.      but output_delayed_branch knows how to deal with it.  */
  332.       return 1;
  333. #else
  334.       return 0;
  335. #endif
  336.  
  337.     case REG:
  338.       return 1;
  339.  
  340.     case MEM:
  341. #if 0
  342.       /* This is not a single insn src, technically,
  343.      but output_delayed_branch knows how to deal with it.  */
  344.       if (GET_CODE (XEXP (op, 0)) == SYMBOL_REF)
  345.     return 0;
  346. #endif
  347.       return 1;
  348.  
  349.       /* We never need to negate or complement constants.  */
  350.     case NEG:
  351.       return (mode != DFmode);
  352.     case NOT:
  353.       return 1;
  354.  
  355.     case COMPARE:
  356.     case MINUS:
  357.       /* If the target is cc0, then these insns will take
  358.      two insns (one being a nop).  */
  359.       return (mode != SFmode && mode != DFmode);
  360.     case PLUS:
  361.     case AND:
  362.     case IOR:
  363.     case XOR:
  364.     case LSHIFT:
  365.     case ASHIFT:
  366.     case ASHIFTRT:
  367.     case LSHIFTRT:
  368.       if ((GET_CODE (XEXP (op, 0)) == CONST_INT && ! SMALL_INT (XEXP (op, 0)))
  369.       || (GET_CODE (XEXP (op, 1)) == CONST_INT && ! SMALL_INT (XEXP (op, 1))))
  370.     return 0;
  371.       return 1;
  372.  
  373.     case SUBREG:
  374.       if (SUBREG_WORD (op) != 0)
  375.     return 0;
  376.       return single_insn_src_p (SUBREG_REG (op), mode);
  377.  
  378.     case SIGN_EXTEND:
  379.     case ZERO_EXTEND:
  380.       /* Lazy... could check for more cases.  */
  381.       if (GET_CODE (XEXP (op, 0)) == MEM
  382.       && ! CONSTANT_ADDRESS_P (XEXP (XEXP (op, 0), 0)))
  383.     return 1;
  384.       return 0;
  385.  
  386.       /* Not doing floating point, since they probably
  387.      take longer than the branch slot they might fill.  */
  388.     case FLOAT_EXTEND:
  389.     case FLOAT_TRUNCATE:
  390.     case FLOAT:
  391.     case FIX:
  392.     case UNSIGNED_FLOAT:
  393.     case UNSIGNED_FIX:
  394.       return 0;
  395.  
  396.     default:
  397.       return 0;
  398.     }
  399. }
  400.  
  401. /* This extra test must be done to verify that a move insn
  402.    really is just one assembler insn.  */
  403.  
  404. int
  405. single_insn_extra_test (dest, src)
  406.      rtx dest, src;
  407. {
  408.   /* Moves between FP regs and CPU regs are two insns.  */
  409.   return (!(GET_CODE (src) == REG
  410.         && GET_CODE (dest) == REG
  411.         && (FP_REG_P (src) != FP_REG_P (dest))));
  412. }
  413.  
  414. /* Nonzero only if this *really* is a single insn operand.  */
  415. int
  416. strict_single_insn_op_p (op, mode)
  417.      rtx op;
  418.      enum machine_mode mode;
  419. {
  420.   if (mode == VOIDmode)
  421.     mode = GET_MODE (op);
  422.  
  423.   switch (GET_CODE (op))
  424.     {
  425.     case CC0:
  426.       return 1;
  427.  
  428.     case CONST_INT:
  429.       if (SMALL_INT (op))
  430.     return 1;
  431.       /* We can put this set insn into delay slot, because this is one
  432.      insn; 'sethi'.  */
  433.       if ((INTVAL (op) & 0x3ff) == 0)
  434.     return 1;
  435.       return 0;
  436.  
  437.     case SYMBOL_REF:
  438.       return 0;
  439.  
  440.     case REG:
  441.       return (mode != DFmode && mode != DImode);
  442.  
  443.     case MEM:
  444.       if (! CONSTANT_ADDRESS_P (XEXP (op, 0)))
  445.     return (mode != DFmode && mode != DImode);
  446.       return 0;
  447.  
  448.       /* We never need to negate or complement constants.  */
  449.     case NEG:
  450.       return (mode != DFmode);
  451.     case NOT:
  452.       return 1;
  453.  
  454.     case COMPARE:
  455.     case MINUS:
  456.       /* If the target is cc0, then these insns will take
  457.      two insns (one being a nop).  */
  458.       return (mode != SFmode && mode != DFmode);
  459.     case PLUS:
  460.     case AND:
  461.     case IOR:
  462.     case XOR:
  463.     case LSHIFT:
  464.     case ASHIFT:
  465.     case ASHIFTRT:
  466.     case LSHIFTRT:
  467.       if ((GET_CODE (XEXP (op, 0)) == CONST_INT && ! SMALL_INT (XEXP (op, 0)))
  468.       || (GET_CODE (XEXP (op, 1)) == CONST_INT && ! SMALL_INT (XEXP (op, 1))))
  469.     return 0;
  470.       return 1;
  471.  
  472.     case SUBREG:
  473.       if (SUBREG_WORD (op) != 0)
  474.     return 0;
  475.       return strict_single_insn_op_p (SUBREG_REG (op), mode);
  476.  
  477.     case SIGN_EXTEND:
  478.     case ZERO_EXTEND:
  479.       if (GET_CODE (XEXP (op, 0)) == MEM
  480.       && ! CONSTANT_ADDRESS_P (XEXP (XEXP (op, 0), 0)))
  481.     return 1;
  482.       return 0;
  483.  
  484.       /* Not doing floating point, since they probably
  485.      take longer than the branch slot they might fill.  */
  486.     case FLOAT_EXTEND:
  487.     case FLOAT_TRUNCATE:
  488.     case FLOAT:
  489.     case FIX:
  490.     case UNSIGNED_FLOAT:
  491.     case UNSIGNED_FIX:
  492.       return 0;
  493.  
  494.     default:
  495.       return 0;
  496.     }
  497. }
  498.  
  499. /* Return truth value of whether OP is a relational operator.  */
  500. int
  501. relop (op, mode)
  502.      rtx op;
  503.      enum machine_mode mode;
  504. {
  505.   switch (GET_CODE (op))
  506.     {
  507.     case EQ:
  508.     case NE:
  509.     case GT:
  510.     case GE:
  511.     case LT:
  512.     case LE:
  513.     case GTU:
  514.     case GEU:
  515.     case LTU:
  516.     case LEU:
  517.       return 1;
  518.     }
  519.   return 0;
  520. }
  521.  
  522. /* Return truth value of wheterh OP is EQ or NE.  */
  523. int
  524. eq_or_neq (op, mode)
  525.      rtx op;
  526.      enum machine_mode mode;
  527. {
  528.   return (GET_CODE (op) == EQ || GET_CODE (op) == NE);
  529. }
  530.  
  531. /* Return truth value of whether OP can be used as an operands in a three
  532.    address arithmetic insn (such as add %o1,7,%l2) of mode MODE.  */
  533.  
  534. int
  535. arith_operand (op, mode)
  536.      rtx op;
  537.      enum machine_mode mode;
  538. {
  539.   return (register_operand (op, mode)
  540.       || (GET_CODE (op) == CONST_INT && SMALL_INT (op)));
  541. }
  542.  
  543. /* Return truth value of whether OP can be used as an operand in a two
  544.    address arithmetic insn (such as set 123456,%o4) of mode MODE.  */
  545.  
  546. int
  547. arith32_operand (op, mode)
  548.      rtx op;
  549.      enum machine_mode mode;
  550. {
  551.   return (register_operand (op, mode) || GET_CODE (op) == CONST_INT);
  552. }
  553.  
  554. /* Return truth value of whether OP is a integer which fits the
  555.    range constraining immediate operands in three-address insns.  */
  556.  
  557. int
  558. small_int (op, mode)
  559.      rtx op;
  560.      enum machine_mode mode;
  561. {
  562.   return (GET_CODE (op) == CONST_INT && SMALL_INT (op));
  563. }
  564.  
  565. /* Return the best assembler insn template
  566.    for moving operands[1] into operands[0] as a fullword.  */
  567.  
  568. static char *
  569. singlemove_string (operands)
  570.      rtx *operands;
  571. {
  572.   if (GET_CODE (operands[0]) == MEM)
  573.     {
  574.       if (GET_CODE (operands[1]) != MEM)
  575.     if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
  576.       {
  577.         if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
  578.            && cc_prev_status.mdep == XEXP (operands[0], 0)))
  579.           output_asm_insn ("sethi %%hi(%m0),%%g1", operands);
  580.         cc_status.flags |= CC_KNOW_HI_G1;
  581.         cc_status.mdep = XEXP (operands[0], 0);
  582.         return "st %1,[%%lo(%m0)+%%g1]";
  583.       }
  584.     else
  585.       return "st %r1,%0";
  586.       else
  587.     {
  588.       rtx xoperands[2];
  589.  
  590.       cc_status.flags &= ~CC_F0_IS_0;
  591.       xoperands[0] = gen_rtx (REG, SFmode, 32);
  592.       xoperands[1] = operands[1];
  593.       output_asm_insn (singlemove_string (xoperands), xoperands);
  594.       xoperands[1] = xoperands[0];
  595.       xoperands[0] = operands[0];
  596.       output_asm_insn (singlemove_string (xoperands), xoperands);
  597.       return "";
  598.     }
  599.     }
  600.   if (GET_CODE (operands[1]) == MEM)
  601.     {
  602.       if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
  603.     {
  604.       if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
  605.          && cc_prev_status.mdep == XEXP (operands[1], 0)))
  606.         output_asm_insn ("sethi %%hi(%m1),%%g1", operands);
  607.       cc_status.flags |= CC_KNOW_HI_G1;
  608.       cc_status.mdep = XEXP (operands[1], 0);
  609.       return "ld [%%lo(%m1)+%%g1],%0";
  610.     }
  611.       return "ld %1,%0";
  612.     }
  613.   return "mov %1,%0";
  614. }
  615.  
  616. /* Output assembler code to perform a doubleword move insn
  617.    with operands OPERANDS.  */
  618.  
  619. char *
  620. output_move_double (operands)
  621.      rtx *operands;
  622. {
  623.   enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
  624.   rtx latehalf[2];
  625.   rtx addreg0 = 0, addreg1 = 0;
  626.  
  627.   /* First classify both operands.  */
  628.  
  629.   if (REG_P (operands[0]))
  630.     optype0 = REGOP;
  631.   else if (offsettable_memref_p (operands[0]))
  632.     optype0 = OFFSOP;
  633.   else if (GET_CODE (operands[0]) == MEM)
  634.     optype0 = MEMOP;
  635.   else
  636.     optype0 = RNDOP;
  637.  
  638.   if (REG_P (operands[1]))
  639.     optype1 = REGOP;
  640.   else if (CONSTANT_P (operands[1])
  641.        || GET_CODE (operands[1]) == CONST_DOUBLE)
  642.     optype1 = CNSTOP;
  643.   else if (offsettable_memref_p (operands[1]))
  644.     optype1 = OFFSOP;
  645.   else if (GET_CODE (operands[1]) == MEM)
  646.     optype1 = MEMOP;
  647.   else
  648.     optype1 = RNDOP;
  649.  
  650.   /* Check for the cases that the operand constraints are not
  651.      supposed to allow to happen.  Abort if we get one,
  652.      because generating code for these cases is painful.  */
  653.  
  654.   if (optype0 == RNDOP || optype1 == RNDOP)
  655.     abort ();
  656.  
  657.   /* If an operand is an unoffsettable memory ref, find a register
  658.      we can increment temporarily to make it refer to the second word.  */
  659.  
  660.   if (optype0 == MEMOP)
  661.     addreg0 = find_addr_reg (XEXP (operands[0], 0));
  662.  
  663.   if (optype1 == MEMOP)
  664.     addreg1 = find_addr_reg (XEXP (operands[1], 0));
  665.  
  666.   /* Ok, we can do one word at a time.
  667.      Normally we do the low-numbered word first,
  668.      but if either operand is autodecrementing then we
  669.      do the high-numbered word first.
  670.  
  671.      In either case, set up in LATEHALF the operands to use
  672.      for the high-numbered word and in some cases alter the
  673.      operands in OPERANDS to be suitable for the low-numbered word.  */
  674.  
  675.   if (optype0 == REGOP)
  676.     latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
  677.   else if (optype0 == OFFSOP)
  678.     latehalf[0] = adj_offsettable_operand (operands[0], 4);
  679.   else
  680.     latehalf[0] = operands[0];
  681.  
  682.   if (optype1 == REGOP)
  683.     latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
  684.   else if (optype1 == OFFSOP)
  685.     latehalf[1] = adj_offsettable_operand (operands[1], 4);
  686.   else if (optype1 == CNSTOP)
  687.     {
  688.       if (CONSTANT_P (operands[1]))
  689.     latehalf[1] = const0_rtx;
  690.       else if (GET_CODE (operands[1]) == CONST_DOUBLE)
  691.     {
  692.       latehalf[1] = gen_rtx (CONST_INT, VOIDmode,
  693.                  CONST_DOUBLE_HIGH (operands[1]));
  694.       operands[1] = gen_rtx (CONST_INT, VOIDmode,
  695.                  CONST_DOUBLE_LOW (operands[1]));
  696.     }
  697.     }
  698.   else
  699.     latehalf[1] = operands[1];
  700.  
  701.   /* If the first move would clobber the source of the second one,
  702.      do them in the other order.
  703.  
  704.      RMS says "This happens only for registers;
  705.      such overlap can't happen in memory unless the user explicitly
  706.      sets it up, and that is an undefined circumstance."
  707.  
  708.      but it happens on the sparc when loading parameter registers,
  709.      so I am going to define that circumstance, and make it work
  710.      as expected.  */
  711.  
  712.   /* Easy case: try moving both words at once.  */
  713.   /* First check for moving between an even/odd register pair
  714.      and a memory location.  */
  715.   if ((optype0 == REGOP && optype1 != REGOP && optype1 != CNSTOP
  716.        && (REGNO (operands[0]) & 1) == 0)
  717.       || (optype0 != REGOP && optype1 != CNSTOP && optype1 == REGOP
  718.       && (REGNO (operands[1]) & 1) == 0))
  719.     {
  720.       rtx op1, op2;
  721.       rtx base = 0, offset = const0_rtx;
  722.  
  723.       /* OP1 gets the register pair, and OP2 gets the memory address.  */
  724.       if (optype0 == REGOP)
  725.     op1 = operands[0], op2 = XEXP (operands[1], 0);
  726.       else
  727.     op1 = operands[1], op2 = XEXP (operands[0], 0);
  728.  
  729.       /* Now see if we can trust the address to be 8-byte aligned.  */
  730.       /* Trust global variables.  */
  731.       if (CONSTANT_ADDRESS_P (op2))
  732.     {
  733.       operands[0] = op1;
  734.       operands[1] = op2;
  735.       if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
  736.          && cc_prev_status.mdep == op2))
  737.         output_asm_insn ("sethi %%hi(%1),%%g1", operands);
  738.       cc_status.flags |= CC_KNOW_HI_G1;
  739.       cc_status.mdep = op2;
  740.       if (op1 == operands[0])
  741.         return "ldd [%%lo(%1)+%%g1],%0";
  742.       else
  743.         return "std [%%lo(%1)+%%g1],%0";
  744.     }
  745.  
  746.       if (GET_CODE (op2) == PLUS)
  747.     {
  748.       if (GET_CODE (XEXP (op2, 0)) == REG)
  749.         base = XEXP (op2, 0), offset = XEXP (op2, 1);
  750.       else if (GET_CODE (XEXP (op2, 1)) == REG)
  751.         base = XEXP (op2, 1), offset = XEXP (op2, 0);
  752.     }
  753.  
  754.       /* Trust round enough offsets from the stack or frame pointer.  */
  755.       if (base
  756.       && (REGNO (base) == FRAME_POINTER_REGNUM
  757.           || REGNO (base) == STACK_POINTER_REGNUM))
  758.     {
  759.       if (GET_CODE (offset) == CONST_INT
  760.           && (INTVAL (offset) & 0x7) == 0)
  761.         {
  762.           if (op1 == operands[0])
  763.         return "ldd %1,%0";
  764.           else
  765.         return "std %1,%0";
  766.         }
  767.     }
  768.       else
  769.     {
  770.       /* We know structs not on the stack are properly aligned.
  771.          Since a double asks for 8-byte alignment,
  772.          we know it must have got that if it is in a struct.
  773.          But a DImode need not be 8-byte aligned, because it could be a
  774.          struct containing two ints or pointers.  */
  775.  
  776.       /* Sun fucks us here.  We cannot trust references
  777.          to doubles via varying addresses.  It might be on the stack
  778.          even if we don't know that it is; and then it might not be
  779.          double-word aligned.  */
  780. #if 0
  781.       if (GET_CODE (operands[1]) == MEM && GET_MODE (operands[1]) == DFmode
  782.           && MEM_IN_STRUCT_P (operands[1]))
  783.         return "ldd %1,%0";
  784.       else if (GET_CODE (operands[0]) == MEM
  785.            && GET_MODE (operands[0]) == DFmode
  786.            && MEM_IN_STRUCT_P (operands[0]))
  787.         return "std %1,%0";
  788. #endif
  789.     }
  790.     }
  791.  
  792.   if (optype0 == REGOP && optype1 == REGOP
  793.       && REGNO (operands[0]) == REGNO (latehalf[1]))
  794.     {
  795.       /* Make any unoffsettable addresses point at high-numbered word.  */
  796.       if (addreg0)
  797.     output_asm_insn ("add %0,0x4,%0", &addreg0);
  798.       if (addreg1)
  799.     output_asm_insn ("add %0,0x4,%0", &addreg1);
  800.  
  801.       /* Do that word.  */
  802.       output_asm_insn (singlemove_string (latehalf), latehalf);
  803.  
  804.       /* Undo the adds we just did.  */
  805.       if (addreg0)
  806.     output_asm_insn ("add %0,-0x4,%0", &addreg0);
  807.       if (addreg1)
  808.     output_asm_insn ("add %0,-0x4,%0", &addreg0);
  809.  
  810.       /* Do low-numbered word.  */
  811.       return singlemove_string (operands);
  812.     }
  813.   else if (optype0 == REGOP && optype1 != REGOP
  814.        && reg_overlap_mentioned_p (operands[0], operands[1]))
  815.     {
  816.       /* Do the late half first.  */
  817.       output_asm_insn (singlemove_string (latehalf), latehalf);
  818.       /* Then clobber.  */
  819.       return singlemove_string (operands);
  820.     }
  821.  
  822.   /* Normal case: do the two words, low-numbered first.  */
  823.  
  824.   output_asm_insn (singlemove_string (operands), operands);
  825.  
  826.   /* Make any unoffsettable addresses point at high-numbered word.  */
  827.   if (addreg0)
  828.     output_asm_insn ("add %0,0x4,%0", &addreg0);
  829.   if (addreg1)
  830.     output_asm_insn ("add %0,0x4,%0", &addreg1);
  831.  
  832.   /* Do that word.  */
  833.   output_asm_insn (singlemove_string (latehalf), latehalf);
  834.  
  835.   /* Undo the adds we just did.  */
  836.   if (addreg0)
  837.     output_asm_insn ("add %0,-0x4,%0", &addreg0);
  838.   if (addreg1)
  839.     output_asm_insn ("add %0,-0x4,%0", &addreg1);
  840.  
  841.   return "";
  842. }
  843.  
  844. static char *
  845. output_fp_move_double (operands)
  846.      rtx *operands;
  847. {
  848.   if (FP_REG_P (operands[0]))
  849.     {
  850.       if (FP_REG_P (operands[1]))
  851.     {
  852.       output_asm_insn ("fmovs %1,%0", operands);
  853.       operands[0] = gen_rtx (REG, VOIDmode, REGNO (operands[0]) + 1);
  854.       operands[1] = gen_rtx (REG, VOIDmode, REGNO (operands[1]) + 1);
  855.       return "fmovs %1,%0";
  856.     }
  857.       if (GET_CODE (operands[1]) == REG)
  858.     {
  859.       if ((REGNO (operands[1]) & 1) == 0)
  860.         return "std %1,[%%fp-8]\n\tldd [%%fp-8],%0";
  861.       else
  862.         {
  863.           rtx xoperands[3];
  864.           xoperands[0] = operands[0];
  865.           xoperands[1] = operands[1];
  866.           xoperands[2] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
  867.           output_asm_insn ("st %2,[%%fp-4]\n\tst %1,[%%fp-8]\n\tldd [%%fp-8],%0", xoperands);
  868.           return "";
  869.         }
  870.     }
  871.       /* Use ldd if known to be aligned.  */
  872.       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
  873.       && (((XEXP (XEXP (operands[1], 0), 0) == frame_pointer_rtx
  874.         || XEXP (XEXP (operands[1], 0), 0) == stack_pointer_rtx)
  875.            && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == CONST_INT
  876.            && (INTVAL (XEXP (XEXP (operands[1], 0), 1)) & 0x7) == 0)
  877. #if 0 /* An array in a structure that is a parm need not be aligned!  */
  878.           /* Arrays are known to be aligned,
  879.          and reg+reg addresses are used (on this machine)
  880.          only for array accesses.  */
  881.           || (REG_P (XEXP (XEXP (operands[1], 0), 0))
  882.           && REG_P (XEXP (XEXP (operands[1], 0), 1)))
  883. #endif
  884.           ))
  885.     return "ldd %1,%0";
  886.       if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
  887.     {
  888.       if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
  889.          && cc_prev_status.mdep == XEXP (operands[1], 0)))
  890.         output_asm_insn ("sethi %%hi(%m1),%%g1", operands);
  891.       cc_status.flags |= CC_KNOW_HI_G1;
  892.       cc_status.mdep = XEXP (operands[1], 0);
  893.       return "ldd [%%lo(%m1)+%%g1],%0";
  894.     }
  895.       /* Otherwise use two ld insns.  */
  896.       {
  897.     rtx xoperands[2];
  898.     output_asm_insn ("ld %1,%0", operands);
  899.     xoperands[0] = gen_rtx (REG, GET_MODE (operands[0]),
  900.                 REGNO (operands[0]) + 1);
  901.     if (GET_CODE (XEXP (operands[1], 0)) == PLUS
  902.         && offsettable_address_p (1, GET_MODE (operands[1]),
  903.                       XEXP (operands[1], 0)))
  904.       {
  905.         xoperands[1] = adj_offsettable_operand (operands[1], 4);
  906.         output_asm_insn ("ld %1,%0", xoperands);
  907.       }
  908.     else if (GET_CODE (XEXP (operands[1], 0)) == PLUS)
  909.       {
  910.         rtx inc_reg = XEXP (XEXP (operands[1], 0), 0);
  911.         if (inc_reg == frame_pointer_rtx
  912.         && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == REG
  913.         && XEXP (XEXP (operands[1], 0), 0) != frame_pointer_rtx)
  914.           inc_reg = XEXP (XEXP (operands[1], 0), 1);
  915.         if (inc_reg == frame_pointer_rtx)
  916.           {
  917.         output_asm_insn ("mov %%fp,%%g1", xoperands);
  918.         inc_reg = gen_rtx (REG, SImode, 1);
  919.           }
  920.         xoperands[1] = inc_reg;
  921.         output_asm_insn ("add 4,%1,%1", xoperands);
  922.         xoperands[1] = operands[1];
  923.         output_asm_insn ("ld %1,%0", xoperands);
  924.         xoperands[1] = inc_reg;
  925.         output_asm_insn ("add -4,%1,%1", xoperands);
  926.       }
  927.     else
  928.       {
  929.         xoperands[1] = gen_rtx (MEM, GET_MODE (operands[1]),
  930.                 plus_constant (XEXP (operands[1], 0), 4));
  931.         output_asm_insn ("ld %1,%0", xoperands);
  932.       }
  933.     return "";
  934.       }
  935.     }
  936.   else if (FP_REG_P (operands[1]))
  937.     {
  938.       if (GET_CODE (operands[0]) == REG)
  939.     {
  940.       if ((REGNO (operands[0]) & 1) == 0)
  941.         return "std %1,[%%fp-8]\n\tldd [%%fp-8],%0";
  942.       else
  943.         {
  944.           rtx xoperands[3];
  945.           xoperands[2] = operands[1];
  946.           xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
  947.           xoperands[0] = operands[0];
  948.           output_asm_insn ("std %2,[%%fp-8]\n\tld [%%fp-4],%1\n\tld [%%fp-8],%0", xoperands);
  949.           return "";
  950.         }
  951.     }
  952.       /* Use std if we can be sure it is well-aligned.  */
  953.       if (GET_CODE (XEXP (operands[0], 0)) == PLUS
  954.       && (((XEXP (XEXP (operands[0], 0), 0) == frame_pointer_rtx
  955.         || XEXP (XEXP (operands[0], 0), 0) == stack_pointer_rtx)
  956.            && GET_CODE (XEXP (XEXP (operands[0], 0), 1)) == CONST_INT
  957.            && (INTVAL (XEXP (XEXP (operands[0], 0), 1)) & 0x7) == 0)
  958. #if 0 /* An array in a structure that is a parm need not be aligned!  */
  959.           /* Arrays are known to be aligned,
  960.          and reg+reg addresses are used (on this machine)
  961.          only for array accesses.  */
  962.           || (REG_P (XEXP (XEXP (operands[0], 0), 0))
  963.           && REG_P (XEXP (XEXP (operands[0], 0), 1)))
  964. #endif
  965.           ))
  966.     return "std %1,%0";
  967.       if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
  968.     {
  969.       if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
  970.          && cc_prev_status.mdep == XEXP (operands[0], 0)))
  971.         output_asm_insn ("sethi %%hi(%m0),%%g1", operands);
  972.       cc_status.flags |= CC_KNOW_HI_G1;
  973.       cc_status.mdep = XEXP (operands[0], 0);
  974.       return "std %1,[%%lo(%m0)+%%g1]";
  975.     }
  976.       /* Otherwise use two st insns.  */
  977.       {
  978.     rtx xoperands[2];
  979.     output_asm_insn ("st %r1,%0", operands);
  980.     xoperands[1] = gen_rtx (REG, GET_MODE (operands[1]),
  981.                 REGNO (operands[1]) + 1);
  982.     if (GET_CODE (XEXP (operands[0], 0)) == PLUS
  983.         && offsettable_address_p (1, GET_MODE (operands[0]),
  984.                       XEXP (operands[0], 0)))
  985.       {
  986.         xoperands[0] = adj_offsettable_operand (operands[0], 4);
  987.         output_asm_insn ("st %r1,%0", xoperands);
  988.       }
  989.     else if (GET_CODE (XEXP (operands[0], 0)) == PLUS)
  990.       {
  991.         rtx inc_reg = XEXP (XEXP (operands[0], 0), 0);
  992.         if (inc_reg == frame_pointer_rtx
  993.         && GET_CODE (XEXP (XEXP (operands[0], 0), 1)) == REG
  994.         && XEXP (XEXP (operands[0], 0), 0) != frame_pointer_rtx)
  995.           inc_reg = XEXP (XEXP (operands[0], 0), 1);
  996.         if (inc_reg == frame_pointer_rtx)
  997.           {
  998.         output_asm_insn ("mov %%fp,%%g1", xoperands);
  999.         inc_reg = gen_rtx (REG, SImode, 1);
  1000.           }
  1001.         xoperands[0] = inc_reg;
  1002.         output_asm_insn ("add 4,%0,%0", xoperands);
  1003.         xoperands[0] = operands[0];
  1004.         output_asm_insn ("st %r1,%0", xoperands);
  1005.         xoperands[0] = inc_reg;
  1006.         output_asm_insn ("add -4,%0,%0", xoperands);
  1007.       }
  1008.     else
  1009.       {
  1010.         xoperands[0] = gen_rtx (MEM, GET_MODE (operands[0]),
  1011.                 plus_constant (XEXP (operands[0], 0), 4));
  1012.         output_asm_insn ("st %r1,%0", xoperands);
  1013.       }
  1014.     return "";
  1015.       }
  1016.     }
  1017.   else abort ();
  1018. }
  1019.  
  1020. /* Return a REG that occurs in ADDR with coefficient 1.
  1021.    ADDR can be effectively incremented by incrementing REG.  */
  1022.  
  1023. static rtx
  1024. find_addr_reg (addr)
  1025.      rtx addr;
  1026. {
  1027.   while (GET_CODE (addr) == PLUS)
  1028.     {
  1029.       if (GET_CODE (XEXP (addr, 0)) == REG
  1030.       && !(GET_CODE (XEXP (addr, 1)) == REG
  1031.            && XEXP (addr, 0) == frame_pointer_rtx))
  1032.     addr = XEXP (addr, 0);
  1033.       else if (GET_CODE (XEXP (addr, 1)) == REG)
  1034.     addr = XEXP (addr, 1);
  1035.       else if (CONSTANT_P (XEXP (addr, 0)))
  1036.     addr = XEXP (addr, 1);
  1037.       else if (CONSTANT_P (XEXP (addr, 1)))
  1038.     addr = XEXP (addr, 0);
  1039.       else
  1040.     abort ();
  1041.     }
  1042.   if (GET_CODE (addr) == REG)
  1043.     return addr;
  1044.   abort ();
  1045. }
  1046.  
  1047. void
  1048. output_sized_memop (opname, mode)
  1049.      char *opname;
  1050.      enum machine_mode mode;
  1051. {
  1052.   extern struct _iobuf *asm_out_file;
  1053.  
  1054.   static char *ld_size_suffix[] = { "ub", "uh", "", "?", "d" };
  1055.   static char *st_size_suffix[] = { "b", "h", "", "?", "d" };
  1056.   char *modename
  1057.     = (opname[0] == 'l' ? ld_size_suffix : st_size_suffix)[GET_MODE_SIZE (mode) >> 1];
  1058.  
  1059.   fprintf (asm_out_file, "\t%s%s", opname, modename);
  1060. }
  1061.  
  1062. /* Output a store-in-memory whose operands are OPERANDS[0,1].
  1063.    OPERANDS[0] is a MEM, and OPERANDS[1] is a reg or zero.  */
  1064.  
  1065. char *
  1066. output_store (operands)
  1067.      rtx *operands;
  1068. {
  1069.   enum machine_mode mode = GET_MODE (operands[0]);
  1070.   rtx address = XEXP (operands[0], 0);
  1071.  
  1072.   cc_status.flags |= CC_KNOW_HI_G1;
  1073.   cc_status.mdep = address;
  1074.  
  1075.   if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
  1076.      && address == cc_prev_status.mdep))
  1077.     {
  1078.       output_asm_insn ("sethi %%hi(%m0),%%g1", operands);
  1079.       cc_prev_status.mdep = address;
  1080.     }
  1081.  
  1082.   /* Store zero in two parts when appropriate.  */
  1083.   if (mode == DFmode && operands[1] == dconst0_rtx)
  1084.     {
  1085.       /* We can't cross a page boundary here because the
  1086.      SYMBOL_REF must be double word aligned, and for this
  1087.      to be the case, SYMBOL_REF+4 cannot cross.  */
  1088.       output_sized_memop ("st", SImode);
  1089.       output_asm_insn ("%r1,[%%g1+%%lo(%m0)]", operands);
  1090.       output_sized_memop ("st", SImode);
  1091.       return "%r1,[%%g1+%%lo(%m0)+4]";
  1092.     }
  1093.  
  1094.   /* Code below isn't smart enough to move a doubleword in two parts,
  1095.      so use output_move_double to do that in the cases that require it.  */
  1096.   if ((mode == DImode || mode == DFmode)
  1097.       && (GET_CODE (operands[1]) == REG
  1098.       && (REGNO (operands[1]) & 1)))
  1099.     return output_move_double (operands);
  1100.  
  1101.   output_sized_memop ("st", mode);
  1102.   return "%r1,[%%g1+%%lo(%m0)]";
  1103. }
  1104.  
  1105. /* Output a fixed-point load-from-memory whose operands are OPERANDS[0,1].
  1106.    OPERANDS[0] is a reg, and OPERANDS[1] is a mem.  */
  1107.  
  1108. char *
  1109. output_load_fixed (operands)
  1110.      rtx *operands;
  1111. {
  1112.   enum machine_mode mode = GET_MODE (operands[0]);
  1113.   rtx address = XEXP (operands[1], 0);
  1114.  
  1115.   /* We don't bother trying to see if we know %hi(address).
  1116.      This is because we are doing a load, and if we know the
  1117.      %hi value, we probably also know that value in memory.  */
  1118.   cc_status.flags |= CC_KNOW_HI_G1;
  1119.   cc_status.mdep = address;
  1120.  
  1121.   if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
  1122.      && address == cc_prev_status.mdep
  1123.      && cc_prev_status.mdep == cc_status.mdep))
  1124.     {
  1125.       output_asm_insn ("sethi %%hi(%m1),%%g1", operands);
  1126.       cc_prev_status.mdep = address;
  1127.     }
  1128.  
  1129.   /* Code below isn't smart enough to do a doubleword in two parts.
  1130.      So handle that case the slow way.  */
  1131.   if (mode == DImode
  1132.       && GET_CODE (operands[0]) == REG   /* Moving to nonaligned reg pair */
  1133.       && (REGNO (operands[0]) & 1))
  1134.     return output_move_double (operands);
  1135.  
  1136.   output_sized_memop ("ld", mode);
  1137.   if (GET_CODE (operands[0]) == REG)
  1138.     return "[%%g1+%%lo(%m1)],%0";
  1139.   abort ();
  1140. }
  1141.  
  1142. /* Output a floating-point load-from-memory whose operands are OPERANDS[0,1].
  1143.    OPERANDS[0] is a reg, and OPERANDS[1] is a mem.
  1144.    We also handle the case where OPERANDS[0] is a mem.  */
  1145.  
  1146. char *
  1147. output_load_floating (operands)
  1148.      rtx *operands;
  1149. {
  1150.   enum machine_mode mode = GET_MODE (operands[0]);
  1151.   rtx address = XEXP (operands[1], 0);
  1152.  
  1153.   /* We don't bother trying to see if we know %hi(address).
  1154.      This is because we are doing a load, and if we know the
  1155.      %hi value, we probably also know that value in memory.  */
  1156.   cc_status.flags |= CC_KNOW_HI_G1;
  1157.   cc_status.mdep = address;
  1158.  
  1159.   if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
  1160.      && address == cc_prev_status.mdep
  1161.      && cc_prev_status.mdep == cc_status.mdep))
  1162.     {
  1163.       output_asm_insn ("sethi %%hi(%m1),%%g1", operands);
  1164.       cc_prev_status.mdep = address;
  1165.     }
  1166.  
  1167.   if (mode == DFmode)
  1168.     {
  1169.       if (REG_P (operands[0]))
  1170.     {
  1171.       if (REGNO (operands[0]) & 1)
  1172.         return output_move_double (operands);
  1173.       else
  1174.         return "ldd [%%g1+%%lo(%m1)],%0";
  1175.     }
  1176.       cc_status.flags &= ~(CC_F0_IS_0|CC_F1_IS_0);
  1177.       output_asm_insn ("ldd [%%g1+%%lo(%m1)],%%f0", operands);
  1178.       operands[1] = gen_rtx (REG, DFmode, 32);
  1179.       return output_fp_move_double (operands);
  1180.     }
  1181.  
  1182.   if (GET_CODE (operands[0]) == MEM)
  1183.     {
  1184.       cc_status.flags &= ~CC_F1_IS_0;
  1185.       output_asm_insn ("ld [%%g1+%%lo(%1)],%%f1", operands);
  1186.       if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
  1187.     {
  1188.       cc_status.mdep = XEXP (operands[0], 0);
  1189.       return "sethi %%hi(%m0),%%g1\n\tst %%f1,[%%g1+%%lo(%m0)]";
  1190.     }
  1191.       else
  1192.     return "st %%f1,%0";
  1193.     }
  1194.   return "ld [%%g1+%%lo(%m1)],%0";
  1195. }
  1196.  
  1197. /* Load the address specified by OPERANDS[3] into the register
  1198.    specified by OPERANDS[0].
  1199.  
  1200.    OPERANDS[3] may be the result of a sum, hence it could either be:
  1201.  
  1202.    (1) CONST
  1203.    (2) REG
  1204.    (2) REG + CONST_INT
  1205.    (3) REG + REG + CONST_INT
  1206.    (4) REG + REG  (special case of 3).
  1207.  
  1208.    Note that (3) is not a legitimate address.
  1209.    All cases are handled here.  */
  1210.  
  1211. void
  1212. output_load_address (operands)
  1213.      rtx *operands;
  1214. {
  1215.   rtx base, offset;
  1216.  
  1217.   if (CONSTANT_P (operands[3]))
  1218.     {
  1219.       output_asm_insn ("set %3,%0", operands);
  1220.       return;
  1221.     }
  1222.  
  1223.   if (REG_P (operands[3]))
  1224.     {
  1225.       if (REGNO (operands[0]) != REGNO (operands[3]))
  1226.     output_asm_insn ("mov %3,%0", operands);
  1227.       return;
  1228.     }
  1229.  
  1230.   if (GET_CODE (operands[3]) != PLUS)
  1231.     abort ();
  1232.  
  1233.   base = XEXP (operands[3], 0);
  1234.   offset = XEXP (operands[3], 1);
  1235.  
  1236.   if (GET_CODE (base) == CONST_INT)
  1237.     {
  1238.       rtx tmp = base;
  1239.       base = offset;
  1240.       offset = tmp;
  1241.     }
  1242.  
  1243.   if (GET_CODE (offset) != CONST_INT)
  1244.     {
  1245.       /* Operand is (PLUS (REG) (REG)).  */
  1246.       base = operands[3];
  1247.       offset = const0_rtx;
  1248.     }
  1249.  
  1250.   if (REG_P (base))
  1251.     {
  1252.       operands[6] = base;
  1253.       operands[7] = offset;
  1254.       if (SMALL_INT (offset))
  1255.     output_asm_insn ("add %6,%7,%0", operands);
  1256.       else
  1257.     output_asm_insn ("set %7,%0\n\tadd %0,%6,%0", operands);
  1258.     }
  1259.   else if (GET_CODE (base) == PLUS)
  1260.     {
  1261.       operands[6] = XEXP (base, 0);
  1262.       operands[7] = XEXP (base, 1);
  1263.       operands[8] = offset;
  1264.  
  1265.       if (SMALL_INT (offset))
  1266.     output_asm_insn ("add %6,%7,%0\n\tadd %0,%8,%0", operands);
  1267.       else
  1268.     output_asm_insn ("set %8,%0\n\tadd %0,%6,%0\n\tadd %0,%7,%0", operands);
  1269.     }
  1270.   else
  1271.     abort ();
  1272. }
  1273.  
  1274. /* Output code to place a size count SIZE in register REG.
  1275.    ALIGN is the size of the unit of transfer.
  1276.  
  1277.    Because block moves are pipelined, we don't include the
  1278.    first element in the transfer of SIZE to REG.  */
  1279.  
  1280. static void
  1281. output_size_for_block_move (size, reg, align)
  1282.      rtx size, reg;
  1283.      rtx align;
  1284. {
  1285.   rtx xoperands[3];
  1286.  
  1287.   xoperands[0] = reg;
  1288.   xoperands[1] = size;
  1289.   xoperands[2] = align;
  1290.   if (GET_CODE (size) == REG)
  1291.     output_asm_insn ("sub %1,%2,%0", xoperands);
  1292.   else
  1293.     {
  1294.       xoperands[1]
  1295.     = gen_rtx (CONST_INT, VOIDmode, INTVAL (size) - INTVAL (align));
  1296.       cc_status.flags &= ~ CC_KNOW_HI_G1;
  1297.       output_asm_insn ("set %1,%0", xoperands);
  1298.     }
  1299. }
  1300.  
  1301. /* Emit code to perform a block move.
  1302.  
  1303.    OPERANDS[0] is the destination.
  1304.    OPERANDS[1] is the source.
  1305.    OPERANDS[2] is the size.
  1306.    OPERANDS[3] is the alignment safe to use.
  1307.    OPERANDS[4] is a register we can safely clobber as a temp.  */
  1308.  
  1309. char *
  1310. output_block_move (operands)
  1311.      rtx *operands;
  1312. {
  1313.   /* A vector for our computed operands.  Note that load_output_address
  1314.      makes use of (and can clobber) up to the 8th element of this vector.  */
  1315.   rtx xoperands[10];
  1316.   rtx zoperands[10];
  1317.   static int movstrsi_label = 0;
  1318.   int i, j;
  1319.   rtx temp1 = operands[4];
  1320.   rtx alignrtx = operands[3];
  1321.   int align = INTVAL (alignrtx);
  1322.  
  1323.   xoperands[0] = operands[0];
  1324.   xoperands[1] = operands[1];
  1325.   xoperands[2] = temp1;
  1326.  
  1327.   /* We can't move more than four bytes at a time
  1328.      because we have only one register to move them through.  */
  1329.   if (align > 4)
  1330.     {
  1331.       align = 4;
  1332.       alignrtx = gen_rtx (CONST_INT, VOIDmode, 4);
  1333.     }
  1334.  
  1335.   /* Since we clobber untold things, nix the condition codes.  */
  1336.   CC_STATUS_INIT;
  1337.  
  1338.   /* Recognize special cases of block moves.  These occur
  1339.      when GNU C++ is forced to treat something as BLKmode
  1340.      to keep it in memory, when its mode could be represented
  1341.      with something smaller.
  1342.  
  1343.      We cannot do this for global variables, since we don't know
  1344.      what pages they don't cross.  Sigh.  */
  1345.   if (GET_CODE (operands[2]) == CONST_INT
  1346.       && INTVAL (operands[2]) <= 16
  1347.       && ! CONSTANT_ADDRESS_P (operands[0])
  1348.       && ! CONSTANT_ADDRESS_P (operands[1]))
  1349.     {
  1350.       int size = INTVAL (operands[2]);
  1351.  
  1352.       cc_status.flags &= ~CC_KNOW_HI_G1;
  1353.       if (align == 1)
  1354.     {
  1355.       if (memory_address_p (QImode, plus_constant (xoperands[0], size))
  1356.           && memory_address_p (QImode, plus_constant (xoperands[1], size)))
  1357.         {
  1358.           /* We will store different integers into this particular RTX.  */
  1359.           xoperands[2] = gen_rtx (CONST_INT, VOIDmode, 13);
  1360.           for (i = size-1; i >= 0; i--)
  1361.         {
  1362.           INTVAL (xoperands[2]) = i;
  1363.           output_asm_insn ("ldub [%a1+%2],%%g1\n\tstb %%g1,[%a0+%2]",
  1364.                    xoperands);
  1365.         }
  1366.           return "";
  1367.         }
  1368.     }
  1369.       else if (align == 2)
  1370.     {
  1371.       if (memory_address_p (HImode, plus_constant (xoperands[0], size))
  1372.           && memory_address_p (HImode, plus_constant (xoperands[1], size)))
  1373.         {
  1374.           /* We will store different integers into this particular RTX.  */
  1375.           xoperands[2] = gen_rtx (CONST_INT, VOIDmode, 13);
  1376.           for (i = (size>>1)-1; i >= 0; i--)
  1377.         {
  1378.           INTVAL (xoperands[2]) = i<<1;
  1379.           output_asm_insn ("lduh [%a1+%2],%%g1\n\tsth %%g1,[%a0+%2]",
  1380.                    xoperands);
  1381.         }
  1382.           return "";
  1383.         }
  1384.     }
  1385.       else
  1386.     {
  1387.       if (memory_address_p (SImode, plus_constant (xoperands[0], size))
  1388.           && memory_address_p (SImode, plus_constant (xoperands[1], size)))
  1389.         {
  1390.           /* We will store different integers into this particular RTX.  */
  1391.           xoperands[2] = gen_rtx (CONST_INT, VOIDmode, 13);
  1392.           for (i = (size>>2)-1; i >= 0; i--)
  1393.         {
  1394.           INTVAL (xoperands[2]) = i<<2;
  1395.           output_asm_insn ("ld [%a1+%2],%%g1\n\tst %%g1,[%a0+%2]",
  1396.                    xoperands);
  1397.         }
  1398.           return "";
  1399.         }
  1400.     }
  1401.     }
  1402.  
  1403.   /* This is the size of the transfer.
  1404.      Either use the register which already contains the size,
  1405.      or use a free register (used by no operands).
  1406.      Also emit code to decrement the size value by ALIGN.  */
  1407.   output_size_for_block_move (operands[2], temp1, alignrtx);
  1408.      
  1409.   zoperands[0] = operands[0];
  1410.   zoperands[3] = plus_constant (operands[0], align);
  1411.   output_load_address (zoperands);
  1412.  
  1413.   xoperands[3] = gen_rtx (CONST_INT, VOIDmode, movstrsi_label++);
  1414.   xoperands[4] = gen_rtx (CONST_INT, VOIDmode, align);
  1415.  
  1416.   if (align == 1)
  1417.     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);
  1418.   else if (align == 2)
  1419.     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);
  1420.   else
  1421.     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);
  1422.   return "";
  1423. }
  1424.  
  1425. /* What the sparc lacks in hardware, make up for in software.
  1426.    Compute a fairly good sequence of shift and add insns
  1427.    to make a multiply happen.  */
  1428.  
  1429. #define ABS(x) ((x) < 0 ? -(x) : x)
  1430.  
  1431. char *
  1432. output_mul_by_constant (insn, operands, unsignedp)
  1433.      rtx insn;
  1434.      rtx *operands;
  1435.      int unsignedp;
  1436. {
  1437.   int c;            /* Size of constant */
  1438.   int shifts[BITS_PER_WORD];    /* Table of shifts */
  1439.   unsigned int p, log;        /* A power of two, and its log */
  1440.   int d1, d2;            /* Differences of c and p */
  1441.   int first = 1;        /* True if dst has unknown data in it */
  1442.   int i;
  1443.  
  1444.   CC_STATUS_INIT;
  1445.  
  1446.   c = INTVAL (operands[2]);
  1447.   if (c == 0)
  1448.     {
  1449.       /* Does happen, at least when not optimizing.  */
  1450.       if (GET_CODE (operands[0]) == MEM)
  1451.     return "st %%g0,%0";
  1452.       return "mov %%g0,%0";
  1453.     }
  1454.  
  1455.   output_asm_insn ("! start open coded multiply");
  1456.  
  1457.   /* Clear out the table of shifts. */
  1458.   for (i = 0; i < BITS_PER_WORD; ++i)
  1459.     shifts[i] = 0;
  1460.  
  1461.   while (c)
  1462.     {
  1463.       /* Find the power of two nearest ABS(c) */
  1464.       p = 1, log = 0;
  1465.       do
  1466.     {
  1467.       d1 = ABS(c) - p;
  1468.       p *= 2;
  1469.       ++log;
  1470.     }
  1471.       while (p < ABS(c));
  1472.       d2 = p - ABS(c);
  1473.  
  1474.       /* Make an appropriate entry in shifts for p. */
  1475.       if (d2 < d1)
  1476.     {
  1477.       shifts[log] = c < 0 ? -1 : 1;
  1478.       c = c < 0 ? d2 : -d2;
  1479.     }
  1480.       else
  1481.     {
  1482.       shifts[log - 1] = c < 0 ? -1 : 1;
  1483.       c = c < 0 ? -d1 : d1;
  1484.     }
  1485.     }
  1486.  
  1487.   /* Take care of the first insn in sequence.
  1488.      We know we have at least one. */
  1489.  
  1490.   /* A value of -1 in shifts says to subtract that power of two, and a value
  1491.      of 1 says to add that power of two. */
  1492.   for (i = 0; ; i++)
  1493.     if (shifts[i])
  1494.       {
  1495.     if (i)
  1496.       {
  1497.         operands[2] = gen_rtx (CONST_INT, VOIDmode, i);
  1498.         output_asm_insn ("sll %1,%2,%%g1", operands);
  1499.       }
  1500.     else output_asm_insn ("mov %1,%%g1", operands);
  1501.  
  1502.     log = i;
  1503.     if (shifts[i] < 0)
  1504.       output_asm_insn ("sub %%g0,%%g1,%0", operands);
  1505.     else
  1506.       output_asm_insn ("mov %%g1,%0", operands);
  1507.     break;
  1508.       }
  1509.  
  1510.   /* A value of -1 in shifts says to subtract that power of two, and a value
  1511.      of 1 says to add that power of two--continued.  */
  1512.   for (i += 1; i < BITS_PER_WORD; ++i)
  1513.     if (shifts[i])
  1514.       {
  1515.     if (i - log > 0)
  1516.       {
  1517.         operands[2] = gen_rtx (CONST_INT, VOIDmode, i - log);
  1518.         output_asm_insn ("sll %%g1,%2,%%g1", operands);
  1519.       }
  1520.     else
  1521.       {
  1522.         operands[2] = gen_rtx (CONST_INT, VOIDmode, log - i);
  1523.         output_asm_insn ("sra %%g1,%2,%%g1", operands);
  1524.       }
  1525.     log = i;
  1526.     if (shifts[i] < 0)
  1527.       output_asm_insn ("sub %0,%%g1,%0", operands);
  1528.     else
  1529.       output_asm_insn ("add %0,%%g1,%0", operands);
  1530.       }
  1531.  
  1532.   output_asm_insn ("! end open coded multiply");
  1533.  
  1534.   return "";
  1535. }
  1536.  
  1537. char *
  1538. output_mul_insn (operands, unsignedp)
  1539.      rtx *operands;
  1540.      int unsignedp;
  1541. {
  1542.   int lucky1 = ((unsigned)REGNO (operands[1]) - 8) <= 1;
  1543.   int lucky2 = ((unsigned)REGNO (operands[2]) - 8) <= 1;
  1544.  
  1545.   CC_STATUS_INIT;
  1546.  
  1547.   if (lucky1)
  1548.     {
  1549.       if (lucky2)
  1550.     {
  1551.       if (REGNO (operands[1]) == REGNO (operands[2]))
  1552.         {
  1553.           if (REGNO (operands[1]) == 8)
  1554.         output_asm_insn ("mov %%o0,%%o1");
  1555.           else
  1556.         output_asm_insn ("mov %%o1,%%o0");
  1557.         }
  1558.       output_asm_insn ("call .mul,2\n\tnop", operands);
  1559.     }
  1560.       else
  1561.     {
  1562.       rtx xoperands[2];
  1563.       xoperands[0] = gen_rtx (REG, SImode,
  1564.                   8 ^ (REGNO (operands[1]) == 8));
  1565.       xoperands[1] = operands[2];
  1566.       output_asm_insn ("call .mul,2\n\tmov %1,%0", xoperands);
  1567.     }
  1568.     }
  1569.   else if (lucky2)
  1570.     {
  1571.       rtx xoperands[2];
  1572.       xoperands[0] = gen_rtx (REG, SImode,
  1573.                   8 ^ (REGNO (operands[2]) == 8));
  1574.       xoperands[1] = operands[1];
  1575.       output_asm_insn ("call .mul,2\n\tmov %1,%0", xoperands);
  1576.     }
  1577.   else
  1578.     {
  1579.       output_asm_insn ("mov %1,%%o0\n\tcall .mul,2\n\tmov %2,%%o1",
  1580.                operands);
  1581.     }
  1582.  
  1583.   if (REGNO (operands[0]) == 8)
  1584.     return "";
  1585.   return "mov %%o0,%0";
  1586. }
  1587.  
  1588. /* Make floating point register f0 contain 0.
  1589.    SIZE is the number of registers (including f0)
  1590.    which should contain 0.  */
  1591.  
  1592. void
  1593. make_f0_contain_0 (size)
  1594.      int size;
  1595. {
  1596.   if (size == 1)
  1597.     {
  1598.       if ((cc_status.flags & (CC_F0_IS_0)) == 0)
  1599.     output_asm_insn ("ld [%%fp-16],%%f0", 0);
  1600.       cc_status.flags |= CC_F0_IS_0;
  1601.     }
  1602.   else if (size == 2)
  1603.     {
  1604.       if ((cc_status.flags & CC_F0_IS_0) == 0)
  1605.     output_asm_insn ("ld [%%fp-16],%%f0", 0);
  1606.       if ((cc_status.flags & (CC_F1_IS_0)) == 0)
  1607.     output_asm_insn ("ld [%%fp-12],%%f1", 0);
  1608.       cc_status.flags |= CC_F0_IS_0 | CC_F1_IS_0;
  1609.     }
  1610. }
  1611.  
  1612. /* Since condition codes don't have logical links, we need to keep
  1613.    their setting and use together for set-cc insns.  */
  1614. void
  1615. gen_scc_insn (code, mode, operands)
  1616.      enum rtx_code code;
  1617.      enum machine_mode mode;
  1618.      rtx *operands;
  1619. {
  1620.   extern rtx sequence_stack;
  1621.   rtx last_insn = XEXP (XEXP (sequence_stack, 1), 0);
  1622.   rtx last_pat;
  1623.  
  1624.   /* Skip back over the CLOBBERs that may precede this insn.  */
  1625.   while (last_insn && GET_CODE (last_insn) == INSN
  1626.      && GET_CODE (PATTERN (last_insn)) == CLOBBER)
  1627.     last_insn = PREV_INSN (last_insn);
  1628.   /* We should have found the preceding compare.  */
  1629.   if (last_insn == 0 || GET_CODE (last_insn) != INSN)
  1630.     abort ();
  1631.   last_pat = PATTERN (last_insn);
  1632.   if (GET_CODE (last_pat) != SET
  1633.       || GET_CODE (SET_DEST (last_pat)) != CC0)
  1634.     abort ();
  1635.  
  1636.   /* Turn off that previous insn, now that we have got the data out of it.  */
  1637.   PUT_CODE (last_insn, NOTE);
  1638.   NOTE_LINE_NUMBER (last_insn) = NOTE_INSN_DELETED;
  1639.  
  1640.   /* Emit one replacement insn to compare operands and store result.  */
  1641.   emit_insn (gen_rtx (SET, VOIDmode, operands[0],
  1642.               gen_rtx (code, mode, SET_SRC (last_pat), const0_rtx)));
  1643. }
  1644.  
  1645. /* Output reasonable peephole for set-on-condition-code insns.
  1646.    Note that these insns assume a particular way of defining
  1647.    labels.  Therefore, *both* tm-sparc.h and this function must
  1648.    be changed if a new syntax is needed.  */
  1649.  
  1650. char *
  1651. output_scc_insn (code, operand)
  1652.      enum rtx_code code;
  1653.      rtx operand;
  1654. {
  1655.   rtx xoperands[2];
  1656.   rtx label = gen_label_rtx ();
  1657.   int cc_in_fccr = cc_status.flags & CC_IN_FCCR;
  1658.   int antisymmetric = 0;
  1659.  
  1660.   xoperands[0] = operand;
  1661.   xoperands[1] = label;
  1662.  
  1663.   switch (code)
  1664.     {
  1665.     case NE:
  1666.       if (cc_in_fccr)
  1667.     output_asm_insn ("fbne,a %l0", &label);
  1668.       else
  1669.     output_asm_insn ("bne,a %l0", &label);
  1670.       break;
  1671.     case EQ:
  1672.       if (cc_in_fccr)
  1673.     output_asm_insn ("fbe,a %l0", &label);
  1674.       else
  1675.     output_asm_insn ("be,a %l0", &label);
  1676.       break;
  1677.     case GE:
  1678.       if (cc_in_fccr)
  1679.     output_asm_insn ("fbge,a %l0", &label);
  1680.       else
  1681.     output_asm_insn ("bge,a %l0", &label);
  1682.       antisymmetric = 1;
  1683.       break;
  1684.     case GT:
  1685.       if (cc_in_fccr)
  1686.     output_asm_insn ("fbg,a %l0", &label);
  1687.       else
  1688.     output_asm_insn ("bg,a %l0", &label);
  1689.       antisymmetric = 1;
  1690.       break;
  1691.     case LE:
  1692.       if (cc_in_fccr)
  1693.     output_asm_insn ("fble,a %l0", &label);
  1694.       else
  1695.     output_asm_insn ("ble,a %l0", &label);
  1696.       antisymmetric = 1;
  1697.       break;
  1698.     case LT:
  1699.       if (cc_in_fccr)
  1700.     output_asm_insn ("fbl,a %l0", &label);
  1701.       else
  1702.     output_asm_insn ("bl,a %l0", &label);
  1703.       antisymmetric = 1;
  1704.       break;
  1705.     case GEU:
  1706.       if (cc_in_fccr)
  1707.     abort ();
  1708.       else
  1709.     output_asm_insn ("bgeu,a %l0", &label);
  1710.       antisymmetric = 1;
  1711.       break;
  1712.     case GTU:
  1713.       if (cc_in_fccr)
  1714.     abort ();
  1715.       else
  1716.     output_asm_insn ("bgu,a %l0", &label);
  1717.       antisymmetric = 1;
  1718.       break;
  1719.     case LEU:
  1720.       if (cc_in_fccr)
  1721.     abort ();
  1722.       else
  1723.     output_asm_insn ("bleu,a %l0", &label);
  1724.       antisymmetric = 1;
  1725.       break;
  1726.     case LTU:
  1727.       if (cc_in_fccr)
  1728.     abort ();
  1729.       else
  1730.     output_asm_insn ("blu,a %l0", &label);
  1731.       antisymmetric = 1;
  1732.       break;
  1733.     default:
  1734.       abort ();
  1735.     }
  1736.  
  1737.   if (antisymmetric
  1738.       && (cc_status.flags & CC_REVERSED))
  1739.     output_asm_insn ("orcc %%g0,0,%0\n\torcc %%g0,1,%0\n%l1:", xoperands);
  1740.   else
  1741.     output_asm_insn ("orcc %%g0,1,%0\n\torcc %%g0,0,%0\n%l1:", xoperands);
  1742.   cc_status.flags &= ~CC_IN_FCCR;
  1743.  
  1744.   return "";
  1745. }
  1746.  
  1747. /* Output a delayed branch insn with the delay insn in its
  1748.    branch slot.  The delayed branch insn template is in TEMPLATE,
  1749.    with operands OPERANDS.  The insn in its delay slot is INSN.
  1750.  
  1751.    As a special case, since we know that all memory transfers are via
  1752.    ld/st insns, if we see a (MEM (SYMBOL_REF ...)) we divide the memory
  1753.    reference around the branch as
  1754.  
  1755.     sethi %hi(x),%%g1
  1756.     b ...
  1757.     ld/st [%g1+%lo(x)],...
  1758.  
  1759.    As another special case, we handle loading (SYMBOL_REF ...) and
  1760.    other large constants around branches as well:
  1761.  
  1762.     sethi %hi(x),%0
  1763.     b ...
  1764.     or %0,%lo(x),%1
  1765.  
  1766.    */
  1767.  
  1768. char *
  1769. output_delayed_branch (template, operands, insn)
  1770.      char *template;
  1771.      rtx *operands;
  1772.      rtx insn;
  1773. {
  1774.   extern rtx recog_operand[];
  1775.   rtx src = XVECEXP (PATTERN (insn), 0, 1);
  1776.   rtx dest = XVECEXP (PATTERN (insn), 0, 0);
  1777.  
  1778.   if (GET_CODE (src) == SYMBOL_REF
  1779.       || (GET_CODE (src) == CONST_INT
  1780.       && !(SMALL_INT (src) || (INTVAL (src) & 0x3ff) == 0)))
  1781.     {
  1782.       rtx xoperands[2];
  1783.       xoperands[0] = dest;
  1784.       xoperands[1] = src;
  1785.  
  1786.       /* Output the `sethi' insn.  */
  1787.       output_asm_insn ("sethi %%hi(%1),%0", xoperands);
  1788.  
  1789.       /* Output the branch instruction next.  */
  1790.       output_asm_insn (template, operands);
  1791.  
  1792.       /* Now output the `or' insn.  */
  1793.       output_asm_insn ("or %0,%%lo(%1),%0", xoperands);
  1794.     }
  1795.   else if ((GET_CODE (src) == MEM
  1796.         && CONSTANT_ADDRESS_P (XEXP (src, 0)))
  1797.        || (GET_CODE (dest) == MEM
  1798.            && CONSTANT_ADDRESS_P (XEXP (dest, 0))))
  1799.     {
  1800.       rtx xoperands[2];
  1801.       char *split_template;
  1802.       xoperands[0] = dest;
  1803.       xoperands[1] = src;
  1804.  
  1805.       /* Output the `sethi' insn.  */
  1806.       if (GET_CODE (src) == MEM)
  1807.     {
  1808.       if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
  1809.          && cc_prev_status.mdep == XEXP (operands[1], 0)))
  1810.         output_asm_insn ("sethi %%hi(%m1),%%g1", xoperands);
  1811.       split_template = "ld [%%g1+%%lo(%m1)],%0";
  1812.     }
  1813.       else
  1814.     {
  1815.       if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
  1816.          && cc_prev_status.mdep == XEXP (operands[0], 0)))
  1817.         output_asm_insn ("sethi %%hi(%m0),%%g1", xoperands);
  1818.       split_template = "st %r1,[%%g1+%%lo(%m0)]";
  1819.     }
  1820.  
  1821.       /* Output the branch instruction next.  */
  1822.       output_asm_insn (template, operands);
  1823.  
  1824.       /* Now output the load or store.
  1825.      No need to do a CC_STATUS_INIT, because we are branching anyway.  */
  1826.       output_asm_insn (split_template, xoperands);
  1827.     }
  1828.   else
  1829.     {
  1830.       extern char *insn_template[];
  1831.       extern char *(*insn_outfun[])();
  1832.       int insn_code_number;
  1833.       rtx pat = gen_rtx (SET, VOIDmode, dest, src);
  1834.       rtx delay_insn = gen_rtx (INSN, VOIDmode, 0, 0, 0, pat, -1, 0, 0);
  1835.       int i;
  1836.       extern rtx alter_subreg();
  1837.       extern int insn_n_operands[];
  1838.  
  1839.       /* Output the branch instruction first.  */
  1840.       output_asm_insn (template, operands);
  1841.  
  1842.       /* Now recognize the insn which we put in its delay slot.
  1843.      We must do this after outputing the branch insn,
  1844.      since operands may just be a pointer to `recog_operand'.  */
  1845.       insn_code_number = recog (pat, delay_insn);
  1846.       if (insn_code_number == -1)
  1847.     abort ();
  1848.  
  1849.       for (i = 0; i < insn_n_operands[insn_code_number]; i++)
  1850.     {
  1851.       if (GET_CODE (recog_operand[i]) == SUBREG)
  1852.         recog_operand[i] = alter_subreg (recog_operand[i]);
  1853.     }
  1854.  
  1855.       /* Now get the template for what this insn would
  1856.      have been, without the branch.  Its operands are
  1857.      exactly the same as they would be, so we don't
  1858.      need to do an insn_extract.  */
  1859.       template = insn_template[insn_code_number];
  1860.       if (template == 0)
  1861.     template = (*insn_outfun[insn_code_number]) (recog_operand, delay_insn);
  1862.       output_asm_insn (template, recog_operand);
  1863.     }
  1864.   CC_STATUS_INIT;
  1865.   return "";
  1866. }
  1867.  
  1868. /* Output a newly constructed insn DELAY_INSN.  */
  1869. char *
  1870. output_delay_insn (delay_insn)
  1871.      rtx delay_insn;
  1872. {
  1873.   char *template;
  1874.   extern rtx recog_operand[];
  1875.   extern char call_used_regs[];
  1876.   extern char *insn_template[];
  1877.   extern int insn_n_operands[];
  1878.   extern char *(*insn_outfun[])();
  1879.   extern rtx alter_subreg();
  1880.   int insn_code_number;
  1881.   extern int insn_n_operands[];
  1882.   int i;
  1883.  
  1884.   /* Now recognize the insn which we put in its delay slot.
  1885.      We must do this after outputing the branch insn,
  1886.      since operands may just be a pointer to `recog_operand'.  */
  1887.   insn_code_number = recog_memoized (delay_insn);
  1888.   if (insn_code_number == -1)
  1889.     abort ();
  1890.  
  1891.   /* Extract the operands of this delay insn.  */
  1892.   INSN_CODE (delay_insn) = insn_code_number;
  1893.   insn_extract (delay_insn);
  1894.  
  1895.   /* It is possible that this insn has not been properly scaned by final
  1896.      yet.  If this insn's operands don't appear in the peephole's
  1897.      actual operands, then they won't be fixed up by final, so we
  1898.      make sure they get fixed up here.  -- This is a kludge.  */
  1899.   for (i = 0; i < insn_n_operands[insn_code_number]; i++)
  1900.     {
  1901.       if (GET_CODE (recog_operand[i]) == SUBREG)
  1902.     recog_operand[i] = alter_subreg (recog_operand[i]);
  1903.     }
  1904.  
  1905. #ifdef REGISTER_CONSTRAINTS
  1906.   if (! constrain_operands (insn_code_number))
  1907.     abort ();
  1908. #endif
  1909.  
  1910.   cc_prev_status = cc_status;
  1911.  
  1912.   /* Update `cc_status' for this instruction.
  1913.      The instruction's output routine may change it further.
  1914.      If the output routine for a jump insn needs to depend
  1915.      on the cc status, it should look at cc_prev_status.  */
  1916.  
  1917.   NOTICE_UPDATE_CC (PATTERN (delay_insn), delay_insn);
  1918.  
  1919.   /* Now get the template for what this insn would
  1920.      have been, without the branch.  */
  1921.  
  1922.   template = insn_template[insn_code_number];
  1923.   if (template == 0)
  1924.     template = (*insn_outfun[insn_code_number]) (recog_operand, delay_insn);
  1925.   output_asm_insn (template, recog_operand);
  1926.   return "";
  1927. }
  1928.  
  1929. /* Output the insn HEAD, keeping OPERANDS protected (wherever they are).
  1930.    HEAD comes from the target of some branch, so before we output it,
  1931.    we delete it from the target, lest we execute it twice.  The caller
  1932.    of this function promises that such code motion is permissable.  */
  1933. char *
  1934. output_eager_then_insn (head, operands)
  1935.      rtx head;
  1936.      rtx *operands;
  1937. {
  1938.   extern rtx alter_subreg ();
  1939.   extern int insn_n_operands[];
  1940.   extern rtx recog_operand[];
  1941.   rtx xoperands[MAX_RECOG_OPERANDS];
  1942.   int insn_code_number, i, nbytes;
  1943.   rtx nhead;
  1944.  
  1945.   /* Micro-hack: run peephole on head if it looks like a good idea.
  1946.      Right now there's only one such case worth doing...
  1947.  
  1948.      This could be made smarter if the peephole for ``2-insn combine''
  1949.      were also made smarter.  */
  1950.   if (GET_CODE (PATTERN (head)) == SET
  1951.       && REG_P (SET_SRC (PATTERN (head)))
  1952.       && REG_P (SET_DEST (PATTERN (head)))
  1953.       && (nhead = next_real_insn_no_labels (head))
  1954.       && GET_CODE (nhead) == INSN
  1955.       && GET_CODE (PATTERN (nhead)) == SET
  1956.       && GET_CODE (SET_DEST (PATTERN (nhead))) == CC0
  1957.       && (SET_SRC (PATTERN (nhead)) == SET_SRC (PATTERN (head))
  1958.       || SET_SRC (PATTERN (nhead)) == SET_DEST (PATTERN (head))))
  1959.     /* Something's wrong if this does not fly.  */
  1960.     if (! peephole (head))
  1961.       abort ();
  1962.  
  1963.   /* Save our contents of `operands', since output_delay_insn sets them.  */
  1964.   insn_code_number = recog_memoized (head);
  1965.   nbytes = insn_n_operands[insn_code_number] * sizeof (rtx);
  1966.   bcopy (operands, xoperands, nbytes);
  1967.  
  1968.   /* Output the delay insn, and prevent duplication later.  */
  1969.   delete_insn (head);
  1970.   output_delay_insn (head);
  1971.  
  1972.   /* Restore this insn's operands.  */
  1973.   bcopy (xoperands, operands, nbytes);
  1974. }
  1975.  
  1976. /* Return the next INSN, CALL_INSN or JUMP_INSN after LABEL;
  1977.    or 0, if there is none.  Also return 0 if we cross a label.  */
  1978.  
  1979. rtx
  1980. next_real_insn_no_labels (label)
  1981.      rtx label;
  1982. {
  1983.   register rtx insn = NEXT_INSN (label);
  1984.   register RTX_CODE code;
  1985.  
  1986.   while (insn)
  1987.     {
  1988.       code = GET_CODE (insn);
  1989.       if (code == INSN)
  1990.     {
  1991.       if (GET_CODE (PATTERN (insn)) != CLOBBER
  1992.           && GET_CODE (PATTERN (insn)) != USE)
  1993.         return insn;
  1994.     }
  1995.       if (code == CALL_INSN || code == JUMP_INSN)
  1996.     return insn;
  1997.       if (code == CODE_LABEL)
  1998.     return 0;
  1999.       insn = NEXT_INSN (insn);
  2000.     }
  2001.  
  2002.   return 0;
  2003. }
  2004.  
  2005. int
  2006. operands_satisfy_eager_branch_peephole (operands, conditional)
  2007.      rtx *operands;
  2008.      int conditional;
  2009. {
  2010.   rtx label;
  2011.  
  2012.   if (conditional)
  2013.     {
  2014.       if (GET_CODE (operands[0]) != IF_THEN_ELSE)
  2015.     return 0;
  2016.  
  2017.       if (GET_CODE (XEXP (operands[0], 1)) == LABEL_REF)
  2018.     label = XEXP (XEXP (operands[0], 1), 0);
  2019.       else if (GET_CODE (XEXP (operands[0], 2)) == LABEL_REF)
  2020.     label = XEXP (XEXP (operands[0], 2), 0);
  2021.       else return 0;
  2022.     }
  2023.   else
  2024.     {
  2025.       label = operands[0];
  2026.     }
  2027.  
  2028.   if (LABEL_NUSES (label) == 1)
  2029.     {
  2030.       rtx prev = PREV_INSN (label);
  2031.       while (prev && GET_CODE (prev) == NOTE)
  2032.     prev = PREV_INSN (prev);
  2033.       if (prev == 0
  2034.       || GET_CODE (prev) == BARRIER)
  2035.     {
  2036.       rtx head = next_real_insn_no_labels (label);
  2037.  
  2038.       if (head
  2039.           && ! INSN_DELETED_P (head)
  2040.           && GET_CODE (head) == INSN
  2041.           && GET_CODE (PATTERN (head)) == SET
  2042.           && strict_single_insn_op_p (SET_SRC (PATTERN (head)),
  2043.                       GET_MODE (SET_DEST (PATTERN (head))))
  2044.           && strict_single_insn_op_p (SET_DEST (PATTERN (head)),
  2045.                       GET_MODE (SET_DEST (PATTERN (head))))
  2046.           /* Moves between FP regs and CPU regs are two insns.  */
  2047.           && !(GET_CODE (SET_SRC (PATTERN (head))) == REG
  2048.            && GET_CODE (SET_DEST (PATTERN (head))) == REG
  2049.            && (FP_REG_P (SET_SRC (PATTERN (head)))
  2050.                != FP_REG_P (SET_DEST (PATTERN (head))))))
  2051.         {
  2052.           if (conditional == 2)
  2053.         return (GET_CODE (operands[1]) != PC
  2054.             && safe_insn_src_p (operands[2], VOIDmode)
  2055.             && strict_single_insn_op_p (operands[2], VOIDmode)
  2056.             && operand_clobbered_before_used_after (operands[1], label));
  2057.           return 1;
  2058.         }
  2059.     }
  2060.     }
  2061.  
  2062.   if (conditional == 1
  2063.       && GET_CODE (operands[1]) != PC
  2064.       && safe_insn_src_p (operands[2], VOIDmode)
  2065.       && strict_single_insn_op_p (operands[2], VOIDmode)
  2066.       && operand_clobbered_before_used_after (operands[1], label))
  2067.     return 1;
  2068.  
  2069.   return 0;
  2070. }
  2071.  
  2072.