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