home *** CD-ROM | disk | FTP | other *** search
/ Education Sampler 1992 [NeXTSTEP] / Education_1992_Sampler.iso / NeXT / GnuSource / cc-61.0.1 / cc / config / out-i860.c < prev    next >
C/C++ Source or Header  |  1991-06-03  |  40KB  |  1,518 lines

  1. /* Subroutines for insn-output.c for Intel 860
  2.    Copyright (C) 1989, 1991 Free Software Foundation, Inc.
  3.    Derived from out-sparc.c.
  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.  
  22. #include "config.h"
  23. #include "rtl.h"
  24. #include "regs.h"
  25. #include "hard-reg-set.h"
  26. #include "real.h"
  27. #include "insn-config.h"
  28. #include "conditions.h"
  29. #include "insn-flags.h"
  30. #include "output.h"
  31. #include "insn-attr.h"
  32.  
  33. /* Global variables for machine-dependend things.  */
  34.  
  35. /* This should go away if we pass floats to regs via
  36.    the stack instead of the frame, and if we learn how
  37.    to renumber all the registers when we don't do a save (hard!).  */
  38. extern int frame_pointer_needed;
  39.  
  40. static rtx find_addr_reg ();
  41.  
  42. /* Return non-zero only if OP is a register of mode MODE,
  43.    or const0_rtx.  */
  44. int
  45. reg_or_0_operand (op, mode)
  46.      rtx op;
  47.      enum machine_mode mode;
  48. {
  49.   return (op == const0_rtx || register_operand (op, mode)
  50.       || op == CONST0_RTX (mode));
  51. }
  52.  
  53. /* Return non-zero if this pattern, can be evaluated safely, even if it
  54.    was not asked for.  */
  55. int
  56. safe_insn_src_p (op, mode)
  57.      rtx op;
  58.      enum machine_mode mode;
  59. {
  60.   /* Just experimenting.  */
  61.  
  62.   /* No floating point src is safe if it contains an arithmetic
  63.      operation, since that operation may trap.  */
  64.   switch (GET_CODE (op))
  65.     {
  66.     case CONST_INT:
  67.     case LABEL_REF:
  68.     case SYMBOL_REF:
  69.     case CONST:
  70.       return 1;
  71.  
  72.     case REG:
  73.       return 1;
  74.  
  75.     case MEM:
  76.       return CONSTANT_ADDRESS_P (XEXP (op, 0));
  77.  
  78.       /* We never need to negate or complement constants.  */
  79.     case NEG:
  80.       return (mode != SFmode && mode != DFmode);
  81.     case NOT:
  82.     case ZERO_EXTEND:
  83.       return 1;
  84.  
  85.     case EQ:
  86.     case NE:
  87.     case LT:
  88.     case GT:
  89.     case LE:
  90.     case GE:
  91.     case LTU:
  92.     case GTU:
  93.     case LEU:
  94.     case GEU:
  95.     case MINUS:
  96.     case PLUS:
  97.       return (mode != SFmode && mode != DFmode);
  98.     case AND:
  99.     case IOR:
  100.     case XOR:
  101.     case LSHIFT:
  102.     case ASHIFT:
  103.     case ASHIFTRT:
  104.     case LSHIFTRT:
  105.       if ((GET_CODE (XEXP (op, 0)) == CONST_INT && ! SMALL_INT (XEXP (op, 0)))
  106.       || (GET_CODE (XEXP (op, 1)) == CONST_INT && ! SMALL_INT (XEXP (op, 1))))
  107.     return 0;
  108.       return 1;
  109.  
  110.     default:
  111.       return 0;
  112.     }
  113. }
  114.  
  115. /* Return 1 if REG is clobbered in IN.
  116.    Return 2 if REG is used in IN. 
  117.    Return 3 if REG is both used and clobbered in IN.
  118.    Return 0 if neither.  */
  119.  
  120. static int
  121. reg_clobbered_p (reg, in)
  122.      rtx reg;
  123.      rtx in;
  124. {
  125.   register enum rtx_code code;
  126.  
  127.   if (in == 0)
  128.     return 0;
  129.  
  130.   code = GET_CODE (in);
  131.  
  132.   if (code == SET || code == CLOBBER)
  133.     {
  134.       rtx dest = SET_DEST (in);
  135.       int set = 0;
  136.       int used = 0;
  137.  
  138.       while (GET_CODE (dest) == STRICT_LOW_PART
  139.          || GET_CODE (dest) == SUBREG
  140.          || GET_CODE (dest) == SIGN_EXTRACT
  141.          || GET_CODE (dest) == ZERO_EXTRACT)
  142.     dest = XEXP (dest, 0);
  143.  
  144.       if (dest == reg)
  145.     set = 1;
  146.       else if (GET_CODE (dest) == REG
  147.            && refers_to_regno_p (REGNO (reg),
  148.                      REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
  149.                      SET_DEST (in), 0))
  150.     {
  151.       set = 1;
  152.       /* Anything that sets just part of the register
  153.          is considered using as well as setting it.
  154.          But note that a straight SUBREG of a single-word value
  155.          clobbers the entire value.   */
  156.       if (dest != SET_DEST (in)
  157.           && ! (GET_CODE (SET_DEST (in)) == SUBREG
  158.             || UNITS_PER_WORD >= GET_MODE_SIZE (GET_MODE (dest))))
  159.         used = 1;
  160.     }
  161.  
  162.       if (code == SET)
  163.     {
  164.       if (set)
  165.         used = refers_to_regno_p (REGNO (reg),
  166.                       REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
  167.                       SET_SRC (in), 0);
  168.       else
  169.         used = refers_to_regno_p (REGNO (reg),
  170.                       REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
  171.                       in, 0);
  172.     }
  173.  
  174.       return set + used * 2;
  175.     }
  176.  
  177.   if (refers_to_regno_p (REGNO (reg),
  178.              REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
  179.              in, 0))
  180.     return 2;
  181.   return 0;
  182. }
  183.  
  184. /* Return non-zero if OP can be written to without screwing up
  185.    GCC's model of what's going on.  It is assumed that this operand
  186.    appears in the dest position of a SET insn in a conditional
  187.    branch's delay slot.  AFTER is the label to start looking from.  */
  188. int
  189. operand_clobbered_before_used_after (op, after)
  190.      rtx op;
  191.      rtx after;
  192. {
  193.   extern char call_used_regs[];
  194.  
  195.   /* Just experimenting.  */
  196.   if (GET_CODE (op) == CC0)
  197.     return 1;
  198.   if (GET_CODE (op) == REG)
  199.     {
  200.       rtx insn;
  201.  
  202.       if (op == stack_pointer_rtx)
  203.     return 0;
  204.  
  205.       /* Scan forward from the label, to see if the value of OP
  206.      is clobbered before the first use.  */
  207.  
  208.       for (insn = NEXT_INSN (after); insn; insn = NEXT_INSN (insn))
  209.     {
  210.       if (GET_CODE (insn) == NOTE)
  211.         continue;
  212.       if (GET_CODE (insn) == INSN
  213.           || GET_CODE (insn) == JUMP_INSN
  214.           || GET_CODE (insn) == CALL_INSN)
  215.         {
  216.           switch (reg_clobbered_p (op, PATTERN (insn)))
  217.         {
  218.         default:
  219.           return 0;
  220.         case 1:
  221.           return 1;
  222.         case 0:
  223.           break;
  224.         }
  225.         }
  226.       /* If we reach another label without clobbering OP,
  227.          then we cannot safely write it here.  */
  228.       else if (GET_CODE (insn) == CODE_LABEL)
  229.         return 0;
  230.       if (GET_CODE (insn) == JUMP_INSN)
  231.         {
  232.           if (condjump_p (insn))
  233.         return 0;
  234.           /* This is a jump insn which has already
  235.          been mangled.  We can't tell what it does.  */
  236.           if (GET_CODE (PATTERN (insn)) == PARALLEL)
  237.         return 0;
  238.           if (! JUMP_LABEL (insn))
  239.         return 0;
  240.           /* Keep following jumps.  */
  241.           insn = JUMP_LABEL (insn);
  242.         }
  243.     }
  244.       return 1;
  245.     }
  246.  
  247.   /* In both of these cases, the first insn executed
  248.      for this op will be a orh whatever%h,r0,r31,
  249.      which is tolerable.  */
  250.   if (GET_CODE (op) == MEM)
  251.     return (CONSTANT_ADDRESS_P (XEXP (op, 0)));
  252.  
  253.   return 0;
  254. }
  255.  
  256. /* Return non-zero if this pattern, as a source to a "SET",
  257.    is known to yield an instruction of unit size.  */
  258. int
  259. single_insn_src_p (op, mode)
  260.      rtx op;
  261.      enum machine_mode mode;
  262. {
  263.   switch (GET_CODE (op))
  264.     {
  265.     case CONST_INT:
  266.       /* This is not always a single insn src, technically,
  267.      but output_delayed_branch knows how to deal with it.  */
  268.       return 1;
  269.  
  270.     case SYMBOL_REF:
  271.     case CONST:
  272.       /* This is not a single insn src, technically,
  273.      but output_delayed_branch knows how to deal with it.  */
  274.       return 1;
  275.  
  276.     case REG:
  277.       return 1;
  278.  
  279.     case MEM:
  280.       return 1;
  281.  
  282.       /* We never need to negate or complement constants.  */
  283.     case NEG:
  284.       return (mode != DFmode);
  285.     case NOT:
  286.     case ZERO_EXTEND:
  287.       return 1;
  288.  
  289.     case PLUS:
  290.     case MINUS:
  291.       /* Detect cases that require multiple instructions.  */
  292.       if (CONSTANT_P (XEXP (op, 1))
  293.       && !(GET_CODE (XEXP (op, 1)) == CONST_INT
  294.            && SMALL_INT (XEXP (op, 1))))
  295.     return 0;
  296.     case EQ:
  297.     case NE:
  298.     case LT:
  299.     case GT:
  300.     case LE:
  301.     case GE:
  302.     case LTU:
  303.     case GTU:
  304.     case LEU:
  305.     case GEU:
  306.       /* Not doing floating point, since they probably
  307.      take longer than the branch slot they might fill.  */
  308.       return (mode != SFmode && mode != DFmode);
  309.  
  310.     case AND:
  311.       if (GET_CODE (XEXP (op, 1)) == NOT)
  312.     {
  313.       rtx arg = XEXP (XEXP (op, 1), 0);
  314.       if (CONSTANT_P (arg)
  315.           && !(GET_CODE (arg) == CONST_INT
  316.            && (SMALL_INT (arg)
  317.                || INTVAL (arg) & 0xffff == 0)))
  318.         return 0;
  319.     }
  320.     case IOR:
  321.     case XOR:
  322.       /* Both small and round numbers take one instruction;
  323.      others take two.  */
  324.       if (CONSTANT_P (XEXP (op, 1))
  325.       && !(GET_CODE (XEXP (op, 1)) == CONST_INT
  326.            && (SMALL_INT (XEXP (op, 1))
  327.            || INTVAL (XEXP (op, 1)) & 0xffff == 0)))
  328.     return 0;
  329.  
  330.     case LSHIFT:
  331.     case ASHIFT:
  332.     case ASHIFTRT:
  333.     case LSHIFTRT:
  334.       return 1;
  335.  
  336.     case SUBREG:
  337.       if (SUBREG_WORD (op) != 0)
  338.     return 0;
  339.       return single_insn_src_p (SUBREG_REG (op), mode);
  340.  
  341.       /* Not doing floating point, since they probably
  342.      take longer than the branch slot they might fill.  */
  343.     case FLOAT_EXTEND:
  344.     case FLOAT_TRUNCATE:
  345.     case FLOAT:
  346.     case FIX:
  347.     case UNSIGNED_FLOAT:
  348.     case UNSIGNED_FIX:
  349.       return 0;
  350.  
  351.     default:
  352.       return 0;
  353.     }
  354. }
  355.  
  356. /* Nonzero only if this *really* is a single insn operand.  */
  357. int
  358. strict_single_insn_op_p (op, mode)
  359.      rtx op;
  360.      enum machine_mode mode;
  361. {
  362.   if (mode == VOIDmode)
  363.     mode = GET_MODE (op);
  364.  
  365.   switch (GET_CODE (op))
  366.     {
  367.     case CC0:
  368.       return 1;
  369.  
  370.     case CONST_INT:
  371.       if (SMALL_INT (op))
  372.     return 1;
  373.       /* We can put this set insn into delay slot, because this is one
  374.      insn; 'sethi'.  */
  375.       if ((INTVAL (op) & 0x3ff) == 0)
  376.     return 1;
  377.       return 0;
  378.  
  379.     case SYMBOL_REF:
  380.       return 0;
  381.  
  382.     case REG:
  383. #if 0
  384.       /* This loses when moving an freg to a general reg.  */
  385.       return HARD_REGNO_NREGS (REGNO (op), mode) == 1;
  386. #endif
  387.       return (mode != DFmode && mode != DImode);
  388.  
  389.     case MEM:
  390.       if (! CONSTANT_ADDRESS_P (XEXP (op, 0)))
  391.     return (mode != DFmode && mode != DImode);
  392.       return 0;
  393.  
  394.       /* We never need to negate or complement constants.  */
  395.     case NEG:
  396.       return (mode != DFmode);
  397.     case NOT:
  398.     case ZERO_EXTEND:
  399.       return 1;
  400.  
  401.     case PLUS:
  402.     case MINUS:
  403.       /* Detect cases that require multiple instructions.  */
  404.       if (CONSTANT_P (XEXP (op, 1))
  405.       && !(GET_CODE (XEXP (op, 1)) == CONST_INT
  406.            && SMALL_INT (XEXP (op, 1))))
  407.     return 0;
  408.     case EQ:
  409.     case NE:
  410.     case LT:
  411.     case GT:
  412.     case LE:
  413.     case GE:
  414.     case LTU:
  415.     case GTU:
  416.     case LEU:
  417.     case GEU:
  418.       return 1;
  419.  
  420.     case AND:
  421.       if (GET_CODE (XEXP (op, 1)) == NOT)
  422.     {
  423.       rtx arg = XEXP (XEXP (op, 1), 0);
  424.       if (CONSTANT_P (arg)
  425.           && !(GET_CODE (arg) == CONST_INT
  426.            && (SMALL_INT (arg)
  427.                || INTVAL (arg) & 0xffff == 0)))
  428.         return 0;
  429.     }
  430.     case IOR:
  431.     case XOR:
  432.       /* Both small and round numbers take one instruction;
  433.      others take two.  */
  434.       if (CONSTANT_P (XEXP (op, 1))
  435.       && !(GET_CODE (XEXP (op, 1)) == CONST_INT
  436.            && (SMALL_INT (XEXP (op, 1))
  437.            || INTVAL (XEXP (op, 1)) & 0xffff == 0)))
  438.     return 0;
  439.  
  440.     case LSHIFT:
  441.     case ASHIFT:
  442.     case ASHIFTRT:
  443.     case LSHIFTRT:
  444.       return 1;
  445.  
  446.     case SUBREG:
  447.       if (SUBREG_WORD (op) != 0)
  448.     return 0;
  449.       return strict_single_insn_op_p (SUBREG_REG (op), mode);
  450.  
  451.     case SIGN_EXTEND:
  452.       if (GET_CODE (XEXP (op, 0)) == MEM
  453.       && ! CONSTANT_ADDRESS_P (XEXP (XEXP (op, 0), 0)))
  454.     return 1;
  455.       return 0;
  456.  
  457.       /* Not doing floating point, since they probably
  458.      take longer than the branch slot they might fill.  */
  459.     case FLOAT_EXTEND:
  460.     case FLOAT_TRUNCATE:
  461.     case FLOAT:
  462.     case FIX:
  463.     case UNSIGNED_FLOAT:
  464.     case UNSIGNED_FIX:
  465.       return 0;
  466.  
  467.     default:
  468.       return 0;
  469.     }
  470. }
  471.  
  472. /* Return truth value of whether OP is a relational operator.  */
  473. int
  474. relop (op, mode)
  475.      rtx op;
  476.      enum machine_mode mode;
  477. {
  478.   switch (GET_CODE (op))
  479.     {
  480.     case EQ:
  481.     case NE:
  482.     case GT:
  483.     case GE:
  484.     case LT:
  485.     case LE:
  486.     case GTU:
  487.     case GEU:
  488.     case LTU:
  489.     case LEU:
  490.       return 1;
  491.     }
  492.   return 0;
  493. }
  494.  
  495. /* Return truth value of whether OP can be used as an operands in a three
  496.    address add/subtract insn (such as add %o1,7,%l2) of mode MODE.  */
  497.  
  498. int
  499. arith_operand (op, mode)
  500.      rtx op;
  501.      enum machine_mode mode;
  502. {
  503.   return (register_operand (op, mode)
  504.       || (GET_CODE (op) == CONST_INT && SMALL_INT (op)));
  505. }
  506.  
  507. /* Return 1 if OP is a valid first operand for a logical insn of mode MODE.  */
  508.  
  509. int
  510. logic_operand (op, mode)
  511.      rtx op;
  512.      enum machine_mode mode;
  513. {
  514.   return (register_operand (op, mode)
  515.       || (GET_CODE (op) == CONST_INT && LOGIC_INT (op)));
  516. }
  517.  
  518. /* Return 1 if OP is a valid first operand for either a logical insn
  519.    or an add insn of mode MODE.  */
  520.  
  521. int
  522. compare_operand (op, mode)
  523.      rtx op;
  524.      enum machine_mode mode;
  525. {
  526.   return (register_operand (op, mode)
  527.       || (GET_CODE (op) == CONST_INT && SMALL_INT (op) && LOGIC_INT (op)));
  528. }
  529.  
  530. /* Return truth value of whether OP can be used as an operand
  531.    of a bte insn.  */
  532.  
  533. int
  534. bte_operand (op, mode)
  535.      rtx op;
  536.      enum machine_mode mode;
  537. {
  538.   return (register_operand (op, mode)
  539.       || (GET_CODE (op) == CONST_INT
  540.           && (unsigned) INTVAL (op) < 0x20));
  541. }
  542.  
  543. /* Return 1 if OP is an indexed memory reference of mode MODE.  */
  544.  
  545. int
  546. indexed_operand (op, mode)
  547.      rtx op;
  548.      enum machine_mode mode;
  549. {
  550.   return (GET_CODE (op) == MEM && GET_MODE (op) == mode
  551.       && GET_CODE (XEXP (op, 0)) == PLUS
  552.       && GET_MODE (XEXP (op, 0)) == SImode
  553.       && register_operand (XEXP (XEXP (op, 0), 0), SImode)
  554.       && register_operand (XEXP (XEXP (op, 0), 1), SImode));
  555. }
  556.  
  557. /* Return 1 if OP is a suitable source operand for a load insn
  558.    with mode MODE.  */
  559.  
  560. int
  561. load_operand (op, mode)
  562.      rtx op;
  563.      enum machine_mode mode;
  564. {
  565.   return (memory_operand (op, mode) || indexed_operand (op, mode));
  566. }
  567.  
  568. /* Return truth value of whether OP is a integer which fits the
  569.    range constraining immediate operands in add/subtract insns.  */
  570.  
  571. int
  572. small_int (op, mode)
  573.      rtx op;
  574.      enum machine_mode mode;
  575. {
  576.   return (GET_CODE (op) == CONST_INT && SMALL_INT (op));
  577. }
  578.  
  579. /* Return truth value of whether OP is a integer which fits the
  580.    range constraining immediate operands in logic insns.  */
  581.  
  582. int
  583. logic_int (op, mode)
  584.      rtx op;
  585.      enum machine_mode mode;
  586. {
  587.   return (GET_CODE (op) == CONST_INT && LOGIC_INT (op));
  588. }
  589.  
  590. /* Return the best assembler insn template
  591.    for moving operands[1] into operands[0] as a fullword.  */
  592.  
  593. static char *
  594. singlemove_string (operands)
  595.      rtx *operands;
  596. {
  597.   if (GET_CODE (operands[0]) == MEM)
  598.     {
  599.       if (GET_CODE (operands[1]) != MEM)
  600.     if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
  601.       {
  602.         if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
  603.            && (cc_prev_status.flags & CC_HI_R31_ADJ)
  604.            && cc_prev_status.mdep == XEXP (operands[0], 0)))
  605.           output_asm_insn ("orh ha%%%m0,r0,r31", operands);
  606.         cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
  607.         cc_status.mdep = XEXP (operands[0], 0);
  608.         return "st.l %r1,l%%%m0(r31)";
  609.       }
  610.     else
  611.       return "st.l %r1,%0";
  612.       else
  613.     abort ();
  614. #if 0
  615.     {
  616.       rtx xoperands[2];
  617.  
  618.       cc_status.flags &= ~CC_F0_IS_0;
  619.       xoperands[0] = gen_rtx (REG, SFmode, 32);
  620.       xoperands[1] = operands[1];
  621.       output_asm_insn (singlemove_string (xoperands), xoperands);
  622.       xoperands[1] = xoperands[0];
  623.       xoperands[0] = operands[0];
  624.       output_asm_insn (singlemove_string (xoperands), xoperands);
  625.       return "";
  626.     }
  627. #endif
  628.     }
  629.   if (GET_CODE (operands[1]) == MEM)
  630.     {
  631.       if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
  632.     {
  633.       if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
  634.          && (cc_prev_status.flags & CC_HI_R31_ADJ)
  635.          && cc_prev_status.mdep == XEXP (operands[1], 0)))
  636.         output_asm_insn ("orh ha%%%m1,r0,r31", operands);
  637.       cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
  638.       cc_status.mdep = XEXP (operands[1], 0);
  639.       return "ld.l l%%%m1(r31),%0";
  640.     }
  641.       return "ld.l %1,%0";
  642.     }
  643.   return "mov %1,%0";
  644. }
  645.  
  646. /* Output assembler code to perform a doubleword move insn
  647.    with operands OPERANDS.  */
  648.  
  649. char *
  650. output_move_double (operands)
  651.      rtx *operands;
  652. {
  653.   enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
  654.   rtx latehalf[2];
  655.   rtx addreg0 = 0, addreg1 = 0;
  656.  
  657.   /* First classify both operands.  */
  658.  
  659.   if (REG_P (operands[0]))
  660.     optype0 = REGOP;
  661.   else if (offsettable_memref_p (operands[0]))
  662.     optype0 = OFFSOP;
  663.   else if (GET_CODE (operands[0]) == MEM)
  664.     optype0 = MEMOP;
  665.   else
  666.     optype0 = RNDOP;
  667.  
  668.   if (REG_P (operands[1]))
  669.     optype1 = REGOP;
  670.   else if (CONSTANT_P (operands[1]))
  671.     optype1 = CNSTOP;
  672.   else if (offsettable_memref_p (operands[1]))
  673.     optype1 = OFFSOP;
  674.   else if (GET_CODE (operands[1]) == MEM)
  675.     optype1 = MEMOP;
  676.   else
  677.     optype1 = RNDOP;
  678.  
  679.   /* Check for the cases that the operand constraints are not
  680.      supposed to allow to happen.  Abort if we get one,
  681.      because generating code for these cases is painful.  */
  682.  
  683.   if (optype0 == RNDOP || optype1 == RNDOP)
  684.     abort ();
  685.  
  686.   /* If an operand is an unoffsettable memory ref, find a register
  687.      we can increment temporarily to make it refer to the second word.  */
  688.  
  689.   if (optype0 == MEMOP)
  690.     addreg0 = find_addr_reg (XEXP (operands[0], 0));
  691.  
  692.   if (optype1 == MEMOP)
  693.     addreg1 = find_addr_reg (XEXP (operands[1], 0));
  694.  
  695. /* ??? Perhaps in some cases move double words
  696.    if there is a spare pair of floating regs.  */
  697.  
  698.   /* Ok, we can do one word at a time.
  699.      Normally we do the low-numbered word first,
  700.      but if either operand is autodecrementing then we
  701.      do the high-numbered word first.
  702.  
  703.      In either case, set up in LATEHALF the operands to use
  704.      for the high-numbered word and in some cases alter the
  705.      operands in OPERANDS to be suitable for the low-numbered word.  */
  706.  
  707.   if (optype0 == REGOP)
  708.     latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
  709.   else if (optype0 == OFFSOP)
  710.     latehalf[0] = adj_offsettable_operand (operands[0], 4);
  711.   else
  712.     latehalf[0] = operands[0];
  713.  
  714.   if (optype1 == REGOP)
  715.     latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
  716.   else if (optype1 == OFFSOP)
  717.     latehalf[1] = adj_offsettable_operand (operands[1], 4);
  718.   else if (optype1 == CNSTOP)
  719.     {
  720.       if (GET_CODE (operands[1]) == CONST_DOUBLE)
  721.     split_double (operands[1], &operands[1], &latehalf[1]);
  722.       else if (CONSTANT_P (operands[1]))
  723.     latehalf[1] = const0_rtx;
  724.     }
  725.   else
  726.     latehalf[1] = operands[1];
  727.  
  728.   /* If the first move would clobber the source of the second one,
  729.      do them in the other order.
  730.  
  731.      RMS says "This happens only for registers;
  732.      such overlap can't happen in memory unless the user explicitly
  733.      sets it up, and that is an undefined circumstance."
  734.  
  735.      but it happens on the sparc when loading parameter registers,
  736.      so I am going to define that circumstance, and make it work
  737.      as expected.  */
  738.  
  739.   if (optype0 == REGOP && optype1 == REGOP
  740.       && REGNO (operands[0]) == REGNO (latehalf[1]))
  741.     {
  742.       /* Make any unoffsettable addresses point at high-numbered word.  */
  743.       if (addreg0)
  744.     output_asm_insn ("adds 0x4,%0,%0", &addreg0);
  745.       if (addreg1)
  746.     output_asm_insn ("adds 0x4,%0,%0", &addreg1);
  747.  
  748.       /* Do that word.  */
  749.       output_asm_insn (singlemove_string (latehalf), latehalf);
  750.  
  751.       /* Undo the adds we just did.  */
  752.       if (addreg0)
  753.     output_asm_insn ("adds -0x4,%0,%0", &addreg0);
  754.       if (addreg1)
  755.     output_asm_insn ("adds -0x4,%0,%0", &addreg1);
  756.  
  757.       /* Do low-numbered word.  */
  758.       return singlemove_string (operands);
  759.     }
  760.   else if (optype0 == REGOP && optype1 != REGOP
  761.        && reg_overlap_mentioned_p (operands[0], operands[1]))
  762.     {
  763.       /* Do the late half first.  */
  764.       output_asm_insn (singlemove_string (latehalf), latehalf);
  765.       /* Then clobber.  */
  766.       return singlemove_string (operands);
  767.     }
  768.  
  769.   /* Normal case: do the two words, low-numbered first.  */
  770.  
  771.   output_asm_insn (singlemove_string (operands), operands);
  772.  
  773.   /* Make any unoffsettable addresses point at high-numbered word.  */
  774.   if (addreg0)
  775.     output_asm_insn ("adds 0x4,%0,%0", &addreg0);
  776.   if (addreg1)
  777.     output_asm_insn ("adds 0x4,%0,%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 ("adds -0x4,%0,%0", &addreg0);
  785.   if (addreg1)
  786.     output_asm_insn ("adds -0x4,%0,%0", &addreg1);
  787.  
  788.   return "";
  789. }
  790.  
  791. static char *
  792. output_fp_move_double (operands)
  793.      rtx *operands;
  794. {
  795.   if (FP_REG_P (operands[0]))
  796.     {
  797.       if (FP_REG_P (operands[1]))
  798.     return "fmov.dd %1,%0";
  799.       if (GET_CODE (operands[1]) == REG)
  800.     {
  801.       output_asm_insn ("ixfr %1,%0", operands);
  802.       operands[0] = gen_rtx (REG, VOIDmode, REGNO (operands[0]) + 1);
  803.       operands[1] = gen_rtx (REG, VOIDmode, REGNO (operands[1]) + 1);
  804.       return "ixfr %1,%0";
  805.     }
  806.       if (operands[1] == dconst0_rtx)
  807.     return "fmov.dd f0,%0";
  808.       if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
  809.     {
  810.       if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
  811.          && (cc_prev_status.flags & CC_HI_R31_ADJ)
  812.          && cc_prev_status.mdep == XEXP (operands[1], 0)))
  813.         output_asm_insn ("orh ha%%%m1,r0,r31", operands);
  814.       cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
  815.       cc_status.mdep = XEXP (operands[1], 0);
  816.       return "fld.d l%%%m1(r31),%0";
  817.     }
  818.       return "fld.d %1,%0";
  819.     }
  820.   else if (FP_REG_P (operands[1]))
  821.     {
  822.       if (GET_CODE (operands[0]) == REG)
  823.     {
  824.       output_asm_insn ("fxfr %1,%0", operands);
  825.       operands[0] = gen_rtx (REG, VOIDmode, REGNO (operands[0]) + 1);
  826.       operands[1] = gen_rtx (REG, VOIDmode, REGNO (operands[1]) + 1);
  827.       return "fxfr %1,%0";
  828.     }
  829.       if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
  830.     {
  831.       if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
  832.          && (cc_prev_status.flags & CC_HI_R31_ADJ)
  833.          && cc_prev_status.mdep == XEXP (operands[0], 0)))
  834.         output_asm_insn ("orh ha%%%m0,r0,r31", operands);
  835.       cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
  836.       cc_status.mdep = XEXP (operands[0], 0);
  837.       return "fst.d %1,l%%%m0(r31)";
  838.     }
  839.       return "fst.d %1,%0";
  840.     }
  841.   else abort ();
  842. }
  843.  
  844. /* Return a REG that occurs in ADDR with coefficient 1.
  845.    ADDR can be effectively incremented by incrementing REG.  */
  846.  
  847. static rtx
  848. find_addr_reg (addr)
  849.      rtx addr;
  850. {
  851.   while (GET_CODE (addr) == PLUS)
  852.     {
  853.       if (GET_CODE (XEXP (addr, 0)) == REG)
  854.     addr = XEXP (addr, 0);
  855.       else if (GET_CODE (XEXP (addr, 1)) == REG)
  856.     addr = XEXP (addr, 1);
  857.       else if (CONSTANT_P (XEXP (addr, 0)))
  858.     addr = XEXP (addr, 1);
  859.       else if (CONSTANT_P (XEXP (addr, 1)))
  860.     addr = XEXP (addr, 0);
  861.       else
  862.     abort ();
  863.     }
  864.   if (GET_CODE (addr) == REG)
  865.     return addr;
  866.   abort ();
  867. }
  868.  
  869. /* Return a template for a load instruction with mode MODE and
  870.    arguments from the string ARGS.
  871.  
  872.    This string is in static storage.   */
  873.  
  874. static char *
  875. load_opcode (mode, args, reg)
  876.      enum machine_mode mode;
  877.      char *args;
  878.      rtx reg;
  879. {
  880.   static char buf[30];
  881.   char *opcode;
  882.  
  883.   switch (mode)
  884.     {
  885.     case QImode:
  886.       opcode = "ld.b";
  887.       break;
  888.  
  889.     case HImode:
  890.       opcode = "ld.s";
  891.       break;
  892.  
  893.     case SImode:
  894.     case SFmode:
  895.       if (FP_REG_P (reg))
  896.     opcode = "fld.l";
  897.       else
  898.     opcode = "ld.l";
  899.       break;
  900.  
  901.     case DImode:
  902.       if (!FP_REG_P (reg))
  903.     abort ();
  904.     case DFmode:
  905.       opcode = "fld.d";
  906.       break;
  907.  
  908.     default:
  909.       abort ();
  910.     }
  911.  
  912.   sprintf (buf, "%s %s", opcode, args);
  913.   return buf;
  914. }
  915.  
  916. /* Return a template for a store instruction with mode MODE and
  917.    arguments from the string ARGS.
  918.  
  919.    This string is in static storage.   */
  920.  
  921. static char *
  922. store_opcode (mode, args, reg)
  923.      enum machine_mode mode;
  924.      char *args;
  925.      rtx reg;
  926. {
  927.   static char buf[30];
  928.   char *opcode;
  929.  
  930.   switch (mode)
  931.     {
  932.     case QImode:
  933.       opcode = "st.b";
  934.       break;
  935.  
  936.     case HImode:
  937.       opcode = "st.s";
  938.       break;
  939.  
  940.     case SImode:
  941.     case SFmode:
  942.       if (FP_REG_P (reg))
  943.     opcode = "fst.l";
  944.       else
  945.     opcode = "st.l";
  946.       break;
  947.  
  948.     case DImode:
  949.       if (!FP_REG_P (reg))
  950.     abort ();
  951.     case DFmode:
  952.       opcode = "fst.d";
  953.       break;
  954.  
  955.     default:
  956.       abort ();
  957.     }
  958.  
  959.   sprintf (buf, "%s %s", opcode, args);
  960.   return buf;
  961. }
  962.  
  963. /* Output a store-in-memory whose operands are OPERANDS[0,1].
  964.    OPERANDS[0] is a MEM, and OPERANDS[1] is a reg or zero.
  965.  
  966.    This function returns a template for an insn.
  967.    This is in static storage.
  968.  
  969.    It may also output some insns directly.
  970.    It may alter the values of operands[0] and operands[1].  */
  971.  
  972. char *
  973. output_store (operands)
  974.      rtx *operands;
  975. {
  976.   enum machine_mode mode = GET_MODE (operands[0]);
  977.   rtx address = XEXP (operands[0], 0);
  978.   char *string;
  979.  
  980.   cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
  981.   cc_status.mdep = address;
  982.  
  983.   if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
  984.      && (cc_prev_status.flags & CC_HI_R31_ADJ)
  985.      && address == cc_prev_status.mdep))
  986.     {
  987.       output_asm_insn ("orh ha%%%m0,r0,r31", operands);
  988.       cc_prev_status.mdep = address;
  989.     }
  990.  
  991.   /* Store zero in two parts when appropriate.  */
  992.   if (mode == DFmode && operands[1] == dconst0_rtx)
  993.     return store_opcode (DFmode, "%r1,l%%%m0(r31)", operands[1]);
  994.  
  995.   /* Code below isn't smart enough to move a doubleword in two parts,
  996.      so use output_move_double to do that in the cases that require it.  */
  997.   if ((mode == DImode || mode == DFmode)
  998.       && ! FP_REG_P (operands[1]))
  999.     return output_move_double (operands);
  1000.  
  1001.   return store_opcode (mode, "%r1,l%%%m0(r31)", operands[1]);
  1002. }
  1003.  
  1004. /* Output a load-from-memory whose operands are OPERANDS[0,1].
  1005.    OPERANDS[0] is a reg, and OPERANDS[1] is a mem.
  1006.  
  1007.    This function returns a template for an insn.
  1008.    This is in static storage.
  1009.  
  1010.    It may also output some insns directly.
  1011.    It may alter the values of operands[0] and operands[1].  */
  1012.  
  1013. char *
  1014. output_load (operands)
  1015.      rtx *operands;
  1016. {
  1017.   enum machine_mode mode = GET_MODE (operands[0]);
  1018.   rtx address = XEXP (operands[1], 0);
  1019.  
  1020.   /* We don't bother trying to see if we know %hi(address).
  1021.      This is because we are doing a load, and if we know the
  1022.      %hi value, we probably also know that value in memory.  */
  1023.   cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
  1024.   cc_status.mdep = address;
  1025.  
  1026.   if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
  1027.      && (cc_prev_status.flags & CC_HI_R31_ADJ)
  1028.      && address == cc_prev_status.mdep
  1029.      && cc_prev_status.mdep == cc_status.mdep))
  1030.     {
  1031.       output_asm_insn ("orh ha%%%m1,r0,r31", operands);
  1032.       cc_prev_status.mdep = address;
  1033.     }
  1034.  
  1035.   /* Code below isn't smart enough to move a doubleword in two parts,
  1036.      so use output_move_double to do that in the cases that require it.  */
  1037.   if ((mode == DImode || mode == DFmode)
  1038.       && ! FP_REG_P (operands[0]))
  1039.     return output_move_double (operands);
  1040.  
  1041.   return load_opcode (mode, "l%%%m1(r31),%0", operands[0]);
  1042. }
  1043.  
  1044. /* Load the address specified by OPERANDS[3] into the register
  1045.    specified by OPERANDS[0].
  1046.  
  1047.    OPERANDS[3] may be the result of a sum, hence it could either be:
  1048.  
  1049.    (1) CONST
  1050.    (2) REG
  1051.    (2) REG + CONST_INT
  1052.    (3) REG + REG + CONST_INT
  1053.    (4) REG + REG  (special case of 3).
  1054.  
  1055.    Note that (3) is not a legitimate address.
  1056.    All cases are handled here.  */
  1057.  
  1058. void
  1059. output_load_address (operands)
  1060.      rtx *operands;
  1061. {
  1062.   rtx base, offset;
  1063.  
  1064.   if (CONSTANT_P (operands[3]))
  1065.     {
  1066.       output_asm_insn ("mov %3,%0", operands);
  1067.       return;
  1068.     }
  1069.  
  1070.   if (REG_P (operands[3]))
  1071.     {
  1072.       if (REGNO (operands[0]) != REGNO (operands[3]))
  1073.     output_asm_insn ("mov %3,%0", operands);
  1074.       return;
  1075.     }
  1076.  
  1077.   if (GET_CODE (operands[3]) != PLUS)
  1078.     abort ();
  1079.  
  1080.   base = XEXP (operands[3], 0);
  1081.   offset = XEXP (operands[3], 1);
  1082.  
  1083.   if (GET_CODE (base) == CONST_INT)
  1084.     {
  1085.       rtx tmp = base;
  1086.       base = offset;
  1087.       offset = tmp;
  1088.     }
  1089.  
  1090.   if (GET_CODE (offset) != CONST_INT)
  1091.     {
  1092.       /* Operand is (PLUS (REG) (REG)).  */
  1093.       base = operands[3];
  1094.       offset = const0_rtx;
  1095.     }
  1096.  
  1097.   if (REG_P (base))
  1098.     {
  1099.       operands[6] = base;
  1100.       operands[7] = offset;
  1101.       if (SMALL_INT (offset))
  1102.     output_asm_insn ("adds %7,%6,%0", operands);
  1103.       else
  1104.     output_asm_insn ("mov %7,%0\n\tadds %0,%6,%0", operands);
  1105.     }
  1106.   else if (GET_CODE (base) == PLUS)
  1107.     {
  1108.       operands[6] = XEXP (base, 0);
  1109.       operands[7] = XEXP (base, 1);
  1110.       operands[8] = offset;
  1111.  
  1112.       if (SMALL_INT (offset))
  1113.     output_asm_insn ("adds %6,%7,%0\n\tadds %8,%0,%0", operands);
  1114.       else
  1115.     output_asm_insn ("mov %8,%0\n\tadds %0,%6,%0\n\tadds %0,%7,%0", operands);
  1116.     }
  1117.   else
  1118.     abort ();
  1119. }
  1120.  
  1121. /* Output code to place a size count SIZE in register REG.
  1122.    Because block moves are pipelined, we don't include the
  1123.    first element in the transfer of SIZE to REG.
  1124.    For this, we subtract ALIGN.  (Actually, I think it is not
  1125.    right to subtract on this machine, so right now we don't.)  */
  1126.  
  1127. static void
  1128. output_size_for_block_move (size, reg, align)
  1129.      rtx size, reg, align;
  1130. {
  1131.   rtx xoperands[3];
  1132.  
  1133.   xoperands[0] = reg;
  1134.   xoperands[1] = size;
  1135.   xoperands[2] = align;
  1136.  
  1137. #if 1
  1138.   cc_status.flags &= ~ CC_KNOW_HI_R31;
  1139.   output_asm_insn ("mov %1,%0", xoperands);
  1140. #else
  1141.   if (GET_CODE (size) == REG)
  1142.     output_asm_insn ("sub %2,%1,%0", xoperands);
  1143.   else
  1144.     {
  1145.       xoperands[1]
  1146.     = gen_rtx (CONST_INT, VOIDmode, INTVAL (size) - INTVAL (align));
  1147.       cc_status.flags &= ~ CC_KNOW_HI_R31;
  1148.       output_asm_insn ("mov %1,%0", xoperands);
  1149.     }
  1150. #endif
  1151. }
  1152.  
  1153. /* Emit code to perform a block move.
  1154.  
  1155.    OPERANDS[0] is the destination.
  1156.    OPERANDS[1] is the source.
  1157.    OPERANDS[2] is the size.
  1158.    OPERANDS[3] is the known safe alignment.
  1159.    OPERANDS[4..6] are pseudos we can safely clobber as temps.  */
  1160.  
  1161. char *
  1162. output_block_move (operands)
  1163.      rtx *operands;
  1164. {
  1165.   /* A vector for our computed operands.  Note that load_output_address
  1166.      makes use of (and can clobber) up to the 8th element of this vector.  */
  1167.   rtx xoperands[10];
  1168.   rtx zoperands[10];
  1169.   static int movstrsi_label = 0;
  1170.   int i, j;
  1171.   rtx temp1 = operands[4];
  1172.   rtx alignrtx = operands[3];
  1173.   int align = INTVAL (alignrtx);
  1174.  
  1175.   xoperands[0] = operands[0];
  1176.   xoperands[1] = operands[1];
  1177.   xoperands[2] = temp1;
  1178.  
  1179.   /* We can't move more than four bytes at a time
  1180.      because we have only one register to move them through.  */
  1181.   if (align > 4)
  1182.     {
  1183.       align = 4;
  1184.       alignrtx = gen_rtx (CONST_INT, VOIDmode, 4);
  1185.     }
  1186.  
  1187.   /* Since we clobber untold things, nix the condition codes.  */
  1188.   CC_STATUS_INIT;
  1189.  
  1190.   /* Recognize special cases of block moves.  These occur
  1191.      when GNU C++ is forced to treat something as BLKmode
  1192.      to keep it in memory, when its mode could be represented
  1193.      with something smaller.
  1194.  
  1195.      We cannot do this for global variables, since we don't know
  1196.      what pages they don't cross.  Sigh.  */
  1197.   if (GET_CODE (operands[2]) == CONST_INT
  1198.       && INTVAL (operands[2]) <= 16
  1199.       && ! CONSTANT_ADDRESS_P (operands[0])
  1200.       && ! CONSTANT_ADDRESS_P (operands[1]))
  1201.     {
  1202.       int size = INTVAL (operands[2]);
  1203.       rtx op0 = xoperands[0];
  1204.       rtx op1 = xoperands[1];
  1205.  
  1206.       cc_status.flags &= ~CC_KNOW_HI_R31;
  1207.       if (align == 1)
  1208.     {
  1209.       if (memory_address_p (QImode, plus_constant (op0, size))
  1210.           && memory_address_p (QImode, plus_constant (op1, size)))
  1211.         {
  1212.           for (i = size-1; i >= 0; i--)
  1213.         {
  1214.           xoperands[0] = plus_constant (op0, i);
  1215.           xoperands[1] = plus_constant (op1, i);
  1216.           output_asm_insn ("ld.b %a1,r31\n\tst.b r31,%a0",
  1217.                    xoperands);
  1218.         }
  1219.           return "";
  1220.         }
  1221.     }
  1222.       else if (align == 2)
  1223.     {
  1224.       if (memory_address_p (HImode, plus_constant (op0, size))
  1225.           && memory_address_p (HImode, plus_constant (op1, size)))
  1226.         {
  1227.           for (i = (size>>1)-1; i >= 0; i--)
  1228.         {
  1229.           xoperands[0] = plus_constant (op0, i * 2);
  1230.           xoperands[1] = plus_constant (op1, i * 2);
  1231.           output_asm_insn ("ld.s %a1,r31\n\tst.s r31,%a0",
  1232.                    xoperands);
  1233.         }
  1234.           return "";
  1235.         }
  1236.     }
  1237.       else
  1238.     {
  1239.       if (memory_address_p (SImode, plus_constant (op0, size))
  1240.           && memory_address_p (SImode, plus_constant (op1, size)))
  1241.         {
  1242.           for (i = (size>>2)-1; i >= 0; i--)
  1243.         {
  1244.           xoperands[0] = plus_constant (op0, i * 4);
  1245.           xoperands[1] = plus_constant (op1, i * 4);
  1246.           output_asm_insn ("ld.l %a1,r31\n\tst.l r31,%a0",
  1247.                    xoperands);
  1248.         }
  1249.           return "";
  1250.         }
  1251.     }
  1252.     }
  1253.  
  1254.   /* This is the size of the transfer.
  1255.      Either use the register which already contains the size,
  1256.      or use a free register (used by no operands).  */
  1257.   output_size_for_block_move (operands[2], operands[4], alignrtx);
  1258.  
  1259. #if 0
  1260.   /* Also emit code to decrement the size value by ALIGN.  */
  1261.   zoperands[0] = operands[0];
  1262.   zoperands[3] = plus_constant (operands[0], align);
  1263.   output_load_address (zoperands);
  1264. #endif
  1265.  
  1266.   /* Generate number for unique label.  */
  1267.  
  1268.   xoperands[3] = gen_rtx (CONST_INT, VOIDmode, movstrsi_label++);
  1269.  
  1270.   /* Copy the increment (negative) to a register for bla insn.  */
  1271.  
  1272.   xoperands[4] = gen_rtx (CONST_INT, VOIDmode, - align);
  1273.   xoperands[5] = operands[5];
  1274.   output_asm_insn ("mov %4,%5", xoperands);
  1275.  
  1276.   /* Make available a register which is a temporary.  */
  1277.  
  1278.   xoperands[6] = operands[6];
  1279.  
  1280.   /* Now the actual loop.
  1281.      In xoperands, elements 1 and 0 are the input and output vectors.
  1282.      Element 2 is the loop index.  Element 5 is the increment.  */
  1283.  
  1284.   if (align == 1)
  1285.     {
  1286.       output_asm_insn ("bla %5,%2,.Lm%3", xoperands);
  1287.       output_asm_insn ("adds %0,%2,%6\n.Lm%3:", xoperands);
  1288.  
  1289.       xoperands[3] = gen_rtx (CONST_INT, VOIDmode, movstrsi_label++);
  1290.  
  1291.       output_asm_insn ("adds %1,%2,%1", xoperands);
  1292.       output_asm_insn ("adds %5,%2,%2\n.Lm%3:",  xoperands);
  1293.       output_asm_insn ("ld.b 0(%1),r31", xoperands);
  1294.       output_asm_insn ("adds %5,%1,%1", xoperands);
  1295.       output_asm_insn ("st.b r31,0(%6)", xoperands);
  1296.       output_asm_insn ("bla %5,%2,.Lm%3", xoperands);
  1297.       output_asm_insn ("adds %5,%6,%6", xoperands);
  1298.     }
  1299.   if (align == 2)
  1300.     {
  1301.       output_asm_insn ("bla %5,%2,.Lm%3", xoperands);
  1302.       output_asm_insn ("adds %0,%2,%6\n.Lm%3:", xoperands);
  1303.  
  1304.       xoperands[3] = gen_rtx (CONST_INT, VOIDmode, movstrsi_label++);
  1305.  
  1306.       output_asm_insn ("adds %1,%2,%1", xoperands);
  1307.       output_asm_insn ("adds %5,%2,%2\n.Lm%3:",  xoperands);
  1308.       output_asm_insn ("ld.s 0(%1),r31", xoperands);
  1309.       output_asm_insn ("adds %5,%1,%1", xoperands);
  1310.       output_asm_insn ("st.s r31,0(%6)", xoperands);
  1311.       output_asm_insn ("bla %5,%2,.Lm%3", xoperands);
  1312.       output_asm_insn ("adds %5,%6,%6", xoperands);
  1313.     }
  1314.   if (align == 4)
  1315.     {
  1316.       output_asm_insn ("bla %5,%2,.Lm%3", xoperands);
  1317.       output_asm_insn ("adds %0,%2,%6\n.Lm%3:", xoperands);
  1318.  
  1319.       xoperands[3] = gen_rtx (CONST_INT, VOIDmode, movstrsi_label++);
  1320.  
  1321.       output_asm_insn ("adds %1,%2,%1", xoperands);
  1322.       output_asm_insn ("adds %5,%2,%2\n.Lm%3:",  xoperands);
  1323.       output_asm_insn ("ld.l 0(%1),r31", xoperands);
  1324.       output_asm_insn ("adds %5,%1,%1", xoperands);
  1325.       output_asm_insn ("st.l r31,0(%6)", xoperands);
  1326.       output_asm_insn ("bla %5,%2,.Lm%3", xoperands);
  1327.       output_asm_insn ("adds %5,%6,%6", xoperands);
  1328.     }
  1329.  
  1330.   return "";
  1331. }
  1332.  
  1333. /* Output a delayed branch insn with the delay insn in its
  1334.    branch slot.  The delayed branch insn template is in TEMPLATE,
  1335.    with operands OPERANDS.  The insn in its delay slot is INSN.
  1336.  
  1337.    As a special case, since we know that all memory transfers are via
  1338.    ld/st insns, if we see a (MEM (SYMBOL_REF ...)) we divide the memory
  1339.    reference around the branch as
  1340.  
  1341.     orh ha%x,r0,r31
  1342.     b ...
  1343.     ld/st l%x(r31),...
  1344.  
  1345.    As another special case, we handle loading (SYMBOL_REF ...) and
  1346.    other large constants around branches as well:
  1347.  
  1348.     orh h%x,r0,%0
  1349.     b ...
  1350.     or l%x,%0,%1
  1351.  
  1352.    */
  1353.  
  1354. char *
  1355. output_delayed_branch (template, operands, insn)
  1356.      char *template;
  1357.      rtx *operands;
  1358.      rtx insn;
  1359. {
  1360.   extern rtx recog_operand[];
  1361.   rtx src = XVECEXP (PATTERN (insn), 0, 1);
  1362.   rtx dest = XVECEXP (PATTERN (insn), 0, 0);
  1363.  
  1364.   if (GET_CODE (src) == SYMBOL_REF || GET_CODE (src) == CONST
  1365.       || (GET_CODE (src) == CONST_INT
  1366.       && !(SMALL_INT (src) || (INTVAL (src) & 0xffff) == 0)))
  1367.     {
  1368.       rtx xoperands[2];
  1369.       xoperands[0] = dest;
  1370.       xoperands[1] = src;
  1371.  
  1372.       /* Output the `orh' insn.  */
  1373.       output_asm_insn ("orh h%%%1,r0,%0", xoperands);
  1374.  
  1375.       /* Output the branch instruction next.  */
  1376.       output_asm_insn (template, operands);
  1377.  
  1378.       /* Now output the `or' insn.  */
  1379.       output_asm_insn ("or l%%%1,%0,%0", xoperands);
  1380.     }
  1381.   else if ((GET_CODE (src) == MEM
  1382.         && CONSTANT_ADDRESS_P (XEXP (src, 0)))
  1383.        || (GET_CODE (dest) == MEM
  1384.            && CONSTANT_ADDRESS_P (XEXP (dest, 0))))
  1385.     {
  1386.       rtx xoperands[2];
  1387.       char *split_template;
  1388.       xoperands[0] = dest;
  1389.       xoperands[1] = src;
  1390.  
  1391.       /* Output the `orh' insn.  */
  1392.       if (GET_CODE (src) == MEM)
  1393.     {
  1394.       if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
  1395.          && (cc_prev_status.flags & CC_HI_R31_ADJ)
  1396.          && cc_prev_status.mdep == XEXP (operands[1], 0)))
  1397.         output_asm_insn ("orh ha%%%m1,r0,r31", xoperands);
  1398.       split_template = load_opcode (GET_MODE (dest),
  1399.                     "l%%%m1(r31),%0", dest);
  1400.     }
  1401.       else
  1402.     {
  1403.       if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
  1404.          && (cc_prev_status.flags & CC_HI_R31_ADJ)
  1405.          && cc_prev_status.mdep == XEXP (operands[0], 0)))
  1406.         output_asm_insn ("orh ha%%%m0,r0,r31", xoperands);
  1407.       split_template = store_opcode (GET_MODE (dest),
  1408.                      "%r1,l%%%m0(r31)", src);
  1409.     }
  1410.  
  1411.       /* Output the branch instruction next.  */
  1412.       output_asm_insn (template, operands);
  1413.  
  1414.       /* Now output the load or store.
  1415.      No need to do a CC_STATUS_INIT, because we are branching anyway.  */
  1416.       output_asm_insn (split_template, xoperands);
  1417.     }
  1418.   else
  1419.     {
  1420.       extern char *insn_template[];
  1421.       extern char *(*insn_outfun[])();
  1422.       extern int insn_n_operands[];
  1423.       extern rtx alter_subreg();
  1424.       int insn_code_number;
  1425.       rtx pat = gen_rtx (SET, VOIDmode, dest, src);
  1426.       rtx delay_insn = gen_rtx (INSN, VOIDmode, 0, 0, 0, pat, -1, 0, 0);
  1427.       int i;
  1428.  
  1429.       /* Output the branch instruction first.  */
  1430.       output_asm_insn (template, operands);
  1431.  
  1432.       /* Now recognize the insn which we put in its delay slot.
  1433.      We must do this after outputing the branch insn,
  1434.      since operands may just be a pointer to `recog_operand'.  */
  1435.       insn_code_number = recog (pat, delay_insn);
  1436.       if (insn_code_number == -1)
  1437.     abort ();
  1438.  
  1439.       for (i = 0; i < insn_n_operands[insn_code_number]; i++)
  1440.     {
  1441.       if (GET_CODE (recog_operand[i]) == SUBREG)
  1442.         recog_operand[i] = alter_subreg (recog_operand[i]);
  1443.     }
  1444.  
  1445.       /* Now get the template for what this insn would
  1446.      have been, without the branch.  Its operands are
  1447.      exactly the same as they would be, so we don't
  1448.      need to do an insn_extract.  */
  1449.       template = insn_template[insn_code_number];
  1450.       if (template == 0)
  1451.     template = (*insn_outfun[insn_code_number]) (recog_operand, delay_insn);
  1452.       output_asm_insn (template, recog_operand);
  1453.     }
  1454.   CC_STATUS_INIT;
  1455.   return "";
  1456. }
  1457.  
  1458. /* Output a newly constructed insn DELAY_INSN.  */
  1459. char *
  1460. output_delay_insn (delay_insn)
  1461.      rtx delay_insn;
  1462. {
  1463.   char *template;
  1464.   extern rtx recog_operand[];
  1465.   extern char call_used_regs[];
  1466.   extern char *insn_template[];
  1467.   extern int insn_n_operands[];
  1468.   extern char *(*insn_outfun[])();
  1469.   extern rtx alter_subreg();
  1470.   int insn_code_number;
  1471.   extern int insn_n_operands[];
  1472.   int i;
  1473.  
  1474.   /* Now recognize the insn which we put in its delay slot.
  1475.      We must do this after outputing the branch insn,
  1476.      since operands may just be a pointer to `recog_operand'.  */
  1477.   insn_code_number = recog_memoized (delay_insn);
  1478.   if (insn_code_number == -1)
  1479.     abort ();
  1480.  
  1481.   /* Extract the operands of this delay insn.  */
  1482.   INSN_CODE (delay_insn) = insn_code_number;
  1483.   insn_extract (delay_insn);
  1484.  
  1485.   /* It is possible that this insn has not been properly scaned by final
  1486.      yet.  If this insn's operands don't appear in the peephole's
  1487.      actual operands, then they won't be fixed up by final, so we
  1488.      make sure they get fixed up here.  -- This is a kludge.  */
  1489.   for (i = 0; i < insn_n_operands[insn_code_number]; i++)
  1490.     {
  1491.       if (GET_CODE (recog_operand[i]) == SUBREG)
  1492.     recog_operand[i] = alter_subreg (recog_operand[i]);
  1493.     }
  1494.  
  1495. #ifdef REGISTER_CONSTRAINTS
  1496.   if (! constrain_operands (insn_code_number))
  1497.     abort ();
  1498. #endif
  1499.  
  1500.   cc_prev_status = cc_status;
  1501.  
  1502.   /* Update `cc_status' for this instruction.
  1503.      The instruction's output routine may change it further.
  1504.      If the output routine for a jump insn needs to depend
  1505.      on the cc status, it should look at cc_prev_status.  */
  1506.  
  1507.   NOTICE_UPDATE_CC (PATTERN (delay_insn), delay_insn);
  1508.  
  1509.   /* Now get the template for what this insn would
  1510.      have been, without the branch.  */
  1511.  
  1512.   template = insn_template[insn_code_number];
  1513.   if (template == 0)
  1514.     template = (*insn_outfun[insn_code_number]) (recog_operand, delay_insn);
  1515.   output_asm_insn (template, recog_operand);
  1516.   return "";
  1517. }
  1518.