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

  1. /* Subroutines for insn-output.c for Sun SPARC.
  2.    Copyright (C) 1987-1990 Free Software Foundation, Inc.
  3.    Contributed by Michael Tiemann (tiemann@cygnus.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. #include <stdio.h>
  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. #include "flags.h"
  33.  
  34. char *output_cbranch ();
  35.  
  36. /* Global variables for machine-dependent things.  */
  37.  
  38. /* Save the operands last given to a compare for use when we
  39.    generate a scc or bcc insn.  */
  40.  
  41. rtx sparc_compare_op0, sparc_compare_op1;
  42.  
  43. /* We may need an epilogue if we spill too many registers.
  44.    If this is non-zero, then we branch here for the epilogue.  */
  45. static rtx leaf_label;
  46.  
  47. #ifdef LEAF_REGISTERS
  48.  
  49. /* Vector to say how input registers are mapped to output
  50.    registers.  FRAME_POINTER_REGNUM cannot be remapped by
  51.    this function to eliminate it.  You must use -fomit-frame-pointer
  52.    to get that.  */
  53. char leaf_reg_remap[] =
  54. { 0, 1, 2, 3, 4, 5, 6, 7,
  55.   -1, -1, -1, -1, -1, -1, 14, -1,
  56.   -1, -1, -1, -1, -1, -1, -1, -1,
  57.   8, 9, 10, 11, 12, 13, -1, -1,
  58.  
  59.   32, 33, 34, 35, 36, 37, 38, 39,
  60.   40, 41, 42, 43, 44, 45, 46, 47,
  61.   48, 49, 50, 51, 52, 53, 54, 55,
  62.   56, 57, 58, 59, 60, 61, 62, 63};
  63.  
  64. char leaf_reg_backmap[] =
  65. { 0, 1, 2, 3, 4, 5, 6, 7,
  66.   24, 25, 26, 27, 28, 29, 14, -1,
  67.   -1, -1, -1, -1, -1, -1, -1, -1,
  68.   -1, -1, -1, -1, -1, -1, -1, -1,
  69.  
  70.   32, 33, 34, 35, 36, 37, 38, 39,
  71.   40, 41, 42, 43, 44, 45, 46, 47,
  72.   48, 49, 50, 51, 52, 53, 54, 55,
  73.   56, 57, 58, 59, 60, 61, 62, 63};
  74. #endif
  75.  
  76. /* Global variables set by FUNCTION_PROLOGUE.  */
  77. /* Size of frame.  Need to know this to emit return insns from
  78.    leaf procedures.  */
  79. int apparent_fsize;
  80. int actual_fsize;
  81.  
  82. /* Name of where we pretend to think the frame pointer points.
  83.    Normally, this is "%fp", but if we are in a leaf procedure,
  84.    this is "%sp+something".  */
  85. char *frame_base_name;
  86.  
  87. static rtx find_addr_reg ();
  88.  
  89. /* Return non-zero only if OP is a register of mode MODE,
  90.    or const0_rtx.  */
  91. int
  92. reg_or_0_operand (op, mode)
  93.      rtx op;
  94.      enum machine_mode mode;
  95. {
  96.   return (op == const0_rtx || register_operand (op, mode));
  97. }
  98.  
  99. /* Nonzero if OP can appear as the dest of a RESTORE insn.  */
  100. int
  101. restore_operand (op, mode)
  102.      rtx op;
  103.      enum machine_mode mode;
  104. {
  105.   return (GET_CODE (op) == REG && GET_MODE (op) == mode
  106.       && (REGNO (op) < 8 || (REGNO (op) >= 24 && REGNO (op) < 32)));
  107. }
  108.  
  109. /* PC-relative call insn on SPARC is independent of `memory_operand'.  */
  110.  
  111. int
  112. call_operand (op, mode)
  113.      rtx op;
  114.      enum machine_mode mode;
  115. {
  116.   if (GET_CODE (op) != MEM)
  117.     abort ();
  118.   op = XEXP (op, 0);
  119.   return (REG_P (op) || CONSTANT_P (op));
  120. }
  121.  
  122. int
  123. call_operand_address (op, mode)
  124.      rtx op;
  125.      enum machine_mode mode;
  126. {
  127.   return (REG_P (op) || CONSTANT_P (op));
  128. }
  129.  
  130. /* Returns 1 if OP is either a symbol reference or a sum of a symbol
  131.    reference and a constant.  */
  132.  
  133. int
  134. symbolic_operand (op, mode)
  135.      register rtx op;
  136.      enum machine_mode mode;
  137. {
  138.   switch (GET_CODE (op))
  139.     {
  140.     case SYMBOL_REF:
  141.     case LABEL_REF:
  142.       return 1;
  143.  
  144.     case CONST:
  145.       op = XEXP (op, 0);
  146.       return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
  147.            || GET_CODE (XEXP (op, 0)) == LABEL_REF)
  148.           && GET_CODE (XEXP (op, 1)) == CONST_INT);
  149.  
  150.     default:
  151.       return 0;
  152.     }
  153. }
  154.  
  155. /* Return truth value of statement that OP is a symbolic memory
  156.    operand of mode MODE.  */
  157.  
  158. int
  159. symbolic_memory_operand (op, mode)
  160.      rtx op;
  161.      enum machine_mode mode;
  162. {
  163.   if (GET_CODE (op) == SUBREG)
  164.     op = SUBREG_REG (op);
  165.   if (GET_CODE (op) != MEM)
  166.     return 0;
  167.   op = XEXP (op, 0);
  168.   return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == CONST
  169.       || GET_CODE (op) == HIGH || GET_CODE (op) == LABEL_REF);
  170. }
  171.  
  172. /* Return 1 if the operand is either a register or a memory operand that is
  173.    not symbolic.  */
  174.  
  175. int
  176. reg_or_nonsymb_mem_operand (op, mode)
  177.     register rtx op;
  178.     enum machine_mode mode;
  179. {
  180.   if (register_operand (op, mode))
  181.     return 1;
  182.  
  183.   if (memory_operand (op, mode) && ! symbolic_memory_operand (op, mode))
  184.     return 1;
  185.  
  186.   return 0;
  187. }
  188.  
  189. int
  190. sparc_operand (op, mode)
  191.      rtx op;
  192.      enum machine_mode mode;
  193. {
  194.   if (register_operand (op, mode))
  195.     return 1;
  196.   if (GET_CODE (op) == CONST_INT)
  197.     return SMALL_INT (op);
  198.   if (GET_MODE (op) != mode)
  199.     return 0;
  200.   if (GET_CODE (op) == SUBREG)
  201.     op = SUBREG_REG (op);
  202.   if (GET_CODE (op) != MEM)
  203.     return 0;
  204.  
  205.   op = XEXP (op, 0);
  206.   if (GET_CODE (op) == LO_SUM)
  207.     return (GET_CODE (XEXP (op, 0)) == REG
  208.         && symbolic_operand (XEXP (op, 1), Pmode));
  209.   return memory_address_p (mode, op);
  210. }
  211.  
  212. int
  213. move_operand (op, mode)
  214.      rtx op;
  215.      enum machine_mode mode;
  216. {
  217.   if (register_operand (op, mode))
  218.     return 1;
  219.  
  220. #if 0
  221.   if (GET_CODE (op) == CONST_INT)
  222.     return (SMALL_INT (op) || (INTVAL (op) & 0x3ff) == 0);
  223. #else
  224.   if (op == CONST0_RTX (mode))
  225.     return 1;
  226. #endif
  227.  
  228.   if (GET_MODE (op) != mode)
  229.     return 0;
  230.   if (GET_CODE (op) == SUBREG)
  231.     op = SUBREG_REG (op);
  232.   if (GET_CODE (op) != MEM)
  233.     return 0;
  234.  
  235.   op = XEXP (op, 0);
  236.   if (GET_CODE (op) == LO_SUM)
  237.     return (register_operand (XEXP (op, 0), SImode)
  238.         && CONSTANT_P (XEXP (op, 1)));
  239.   return memory_address_p (mode, op);
  240. }
  241.  
  242. int
  243. move_reg_or_immed_operand (op, mode)
  244.      rtx op;
  245.      enum machine_mode mode;
  246. {
  247.   if (register_operand (op, mode))
  248.     return 1;
  249.   if (GET_CODE (op) == CONST_INT)
  250.     return (SMALL_INT (op) || (INTVAL (op) & 0x3ff) == 0);
  251.   /* Special case for PIC.  */
  252.   if (flag_pic && GET_CODE (op) == LABEL_REF)
  253.     return 1;
  254.   return 0;
  255. }
  256.  
  257. extern rtx force_reg (), validize_mem ();
  258.  
  259. /* The rtx for the global offset table which is a special form
  260.    that *is* a position independent symbolic constant.  */
  261. rtx pic_pc_rtx;
  262.  
  263. /* Ensure that we are not using patterns that are not OK with PIC.  */
  264.  
  265. int
  266. check_pic (i)
  267.      int i;
  268. {
  269.   extern rtx recog_operand[];
  270.   switch (flag_pic)
  271.     {
  272.     case 1:
  273.       if (GET_CODE (recog_operand[i]) == SYMBOL_REF
  274.       || (GET_CODE (recog_operand[i]) == CONST
  275.           && ! rtx_equal_p (pic_pc_rtx, recog_operand[i])))
  276.     abort ();
  277.     case 2:
  278.     default:
  279.       return 1;
  280.     }
  281. }
  282.  
  283. int
  284. memop (op, mode)
  285.      rtx op;
  286.      enum machine_mode mode;
  287. {
  288.   if (GET_CODE (op) == MEM)
  289.     return (mode == VOIDmode || mode == GET_MODE (op));
  290.   return 0;
  291. }
  292.  
  293. /* Return truth value of whether OP is EQ or NE.  */
  294.  
  295. int
  296. eq_or_neq (op, mode)
  297.      rtx op;
  298.      enum machine_mode mode;
  299. {
  300.   return (GET_CODE (op) == EQ || GET_CODE (op) == NE);
  301. }
  302.  
  303. /* Return 1 if this is a comparison operator, but not an EQ, NE, GEU,
  304.    or LTU for non-floating-point.  We handle those specially.  */
  305.  
  306. int
  307. normal_comp_operator (op, mode)
  308.      rtx op;
  309.      enum machine_mode mode;
  310. {
  311.   enum rtx_code code = GET_CODE (op);
  312.  
  313.   if (GET_RTX_CLASS (code) != '<')
  314.     return 0;
  315.  
  316.   if (GET_MODE (XEXP (op, 0)) == CCFPmode)
  317.     return 1;
  318.  
  319.   return (code != NE && code != EQ && code != GEU && code != LTU);
  320. }
  321.  
  322. /* Return 1 if this is a comparison operator.  This allows the use of
  323.    MATCH_OPERATOR to recognize all the branch insns.  */
  324.  
  325. int
  326. noov_compare_op (op, mode)
  327.     register rtx op;
  328.     enum machine_mode mode;
  329. {
  330.   enum rtx_code code = GET_CODE (op);
  331.  
  332.   if (GET_RTX_CLASS (code) != '<')
  333.     return 0;
  334.  
  335.   if (GET_MODE (XEXP (op, 0)) == CC_NOOVmode)
  336.     /* These are the only branches which work with CC_NOOVmode.  */
  337.     return (code == EQ || code == NE || code == GE || code == LT);
  338.   return 1;
  339. }
  340.  
  341. /* Return 1 if this is a SIGN_EXTEND or ZERO_EXTEND operation.  */
  342.  
  343. int
  344. extend_op (op, mode)
  345.      rtx op;
  346.      enum machine_mode mode;
  347. {
  348.   return GET_CODE (op) == SIGN_EXTEND || GET_CODE (op) == ZERO_EXTEND;
  349. }
  350.  
  351. /* Return nonzero if OP is an operator of mode MODE which can set
  352.    the condition codes explicitly.  We do not include PLUS and MINUS
  353.    because these require CC_NOOVmode, which we handle explicitly.  */
  354.  
  355. int
  356. cc_arithop (op, mode)
  357.      rtx op;
  358.      enum machine_mode mode;
  359. {
  360.   if (GET_CODE (op) == AND
  361.       || GET_CODE (op) == IOR
  362.       || GET_CODE (op) == XOR)
  363.     return 1;
  364.  
  365.   return 0;
  366. }
  367.  
  368. /* Return nonzero if OP is an operator of mode MODE which can bitwise
  369.    complement its second operand and set the condition codes explicitly.  */
  370.  
  371. int
  372. cc_arithopn (op, mode)
  373.      rtx op;
  374.      enum machine_mode mode;
  375. {
  376.   /* XOR is not here because combine canonicalizes (xor (not ...) ...)
  377.      and (xor ... (not ...)) to (not (xor ...)).   */
  378.   return (GET_CODE (op) == AND
  379.       || GET_CODE (op) == IOR);
  380. }
  381.  
  382. /* Return truth value of whether OP can be used as an operands in a three
  383.    address arithmetic insn (such as add %o1,7,%l2) of mode MODE.  */
  384.  
  385. int
  386. arith_operand (op, mode)
  387.      rtx op;
  388.      enum machine_mode mode;
  389. {
  390.   return (register_operand (op, mode)
  391.       || (GET_CODE (op) == CONST_INT && SMALL_INT (op)));
  392. }
  393.  
  394. /* Return truth value of whether OP can be used as an operand in a two
  395.    address arithmetic insn (such as set 123456,%o4) of mode MODE.  */
  396.  
  397. int
  398. arith32_operand (op, mode)
  399.      rtx op;
  400.      enum machine_mode mode;
  401. {
  402.   return (register_operand (op, mode) || GET_CODE (op) == CONST_INT);
  403. }
  404.  
  405. /* Return truth value of whether OP is a register or a CONST_DOUBLE.  */
  406.  
  407. int
  408. arith_double_operand (op, mode)
  409.      rtx op;
  410.      enum machine_mode mode;
  411. {
  412.   return (register_operand (op, mode)
  413.       || (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == mode));
  414. }
  415.  
  416. /* Return truth value of whether OP is a integer which fits the
  417.    range constraining immediate operands in three-address insns.  */
  418.  
  419. int
  420. small_int (op, mode)
  421.      rtx op;
  422.      enum machine_mode mode;
  423. {
  424.   return (GET_CODE (op) == CONST_INT && SMALL_INT (op));
  425. }
  426.  
  427. /* Return truth value of statement that OP is a call-clobbered register.  */
  428. int
  429. clobbered_register (op, mode)
  430.      rtx op;
  431.      enum machine_mode mode;
  432. {
  433.   return (GET_CODE (op) == REG && call_used_regs[REGNO (op)]);
  434. }
  435.  
  436. /* X and Y are two things to compare using CODE.  Emit the compare insn and
  437.    return the rtx for register 0 in the proper mode.  */
  438.  
  439. rtx
  440. gen_compare_reg (code, x, y)
  441.      enum rtx_code code;
  442.      rtx x, y;
  443. {
  444.   enum machine_mode mode = SELECT_CC_MODE (code, x);
  445.   rtx cc_reg = gen_rtx (REG, mode, 0);
  446.  
  447.   emit_insn (gen_rtx (SET, VOIDmode, cc_reg,
  448.               gen_rtx (COMPARE, mode, x, y)));
  449.  
  450.   return cc_reg;
  451. }
  452.  
  453. /* Return nonzero if a return peephole merging return with
  454.    setting of output register is ok.  */
  455. int
  456. leaf_return_peephole_ok ()
  457. {
  458.   return (actual_fsize == 0);
  459. }
  460.  
  461. /* Return nonzero if TRIAL can go into the function epilogue's
  462.    delay slot.  SLOT is the slot we are trying to fill.  */
  463.  
  464. int
  465. eligible_for_epilogue_delay (trial, slot)
  466.      rtx trial;
  467.      int slot;
  468. {
  469.   static char *this_function_name;
  470.   rtx pat, src;
  471.  
  472.   if (slot >= 1)
  473.     return 0;
  474.   if (GET_CODE (trial) != INSN
  475.       || GET_CODE (PATTERN (trial)) != SET)
  476.     return 0;
  477.   if (get_attr_length (trial) != 1)
  478.     return 0;
  479.  
  480.   /* In the case of a true leaf function, anything can
  481.      go into the delay slot.  */
  482.   if (leaf_function)
  483.     {
  484.       if (leaf_return_peephole_ok ())
  485.     return (get_attr_in_branch_delay (trial) == IN_BRANCH_DELAY_TRUE);
  486.       return 0;
  487.     }
  488.  
  489.   /* Otherwise, only operations which can be done in tandem with
  490.      a `restore' insn can go into the delay slot.  */
  491.   pat = PATTERN (trial);
  492.   if (GET_CODE (SET_DEST (pat)) != REG
  493.       || REGNO (SET_DEST (pat)) == 0
  494.       || (leaf_function
  495.       && REGNO (SET_DEST (pat)) < 32
  496.       && REGNO (SET_DEST (pat)) >= 16))
  497.     return 0;
  498.   src = SET_SRC (pat);
  499.   if (arith_operand (src, GET_MODE (src)))
  500.     return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (SImode);
  501.   if (GET_CODE (src) == PLUS)
  502.     {
  503.       if (register_operand (XEXP (src, 0), SImode)
  504.       && arith_operand (XEXP (src, 1), SImode))
  505.     return 1;
  506.       if (register_operand (XEXP (src, 1), SImode)
  507.       && arith_operand (XEXP (src, 0), SImode))
  508.     return 1;
  509.     }
  510.   if (GET_CODE (src) == MINUS
  511.       && register_operand (XEXP (src, 0), SImode)
  512.       && small_int (XEXP (src, 1), VOIDmode))
  513.     return 1;
  514.   return 0;
  515. }
  516.  
  517. int
  518. short_branch (uid1, uid2)
  519.      int uid1, uid2;
  520. {
  521.   extern int *insn_addresses;
  522.   unsigned int delta = insn_addresses[uid1] - insn_addresses[uid2];
  523.   if (delta + 1024 < 2048)
  524.     return 1;
  525.   /* warning ("long branch, distance %d", delta); */
  526.   return 0;
  527. }
  528.  
  529. /* Return non-zero if REG is not used after INSN.
  530.    We assume REG is a reload reg, and therefore does
  531.    not live past labels or calls or jumps.  */
  532. int
  533. reg_unused_after (reg, insn)
  534.      rtx reg;
  535.      rtx insn;
  536. {
  537.   enum rtx_code code, prev_code = UNKNOWN;
  538.  
  539.   while (insn = NEXT_INSN (insn))
  540.     {
  541.       if (prev_code == CALL_INSN || prev_code == JUMP_INSN)
  542.     return call_used_regs[REGNO (reg)];
  543.  
  544.       code = GET_CODE (insn);
  545.       if (GET_CODE (insn) == CODE_LABEL)
  546.     return 1;
  547.  
  548.       if (GET_RTX_CLASS (code) == 'i')
  549.     {
  550.       rtx set = single_set (insn);
  551.       int in_src = set && reg_overlap_mentioned_p (reg, SET_SRC (set));
  552.       if (set && in_src)
  553.         return 0;
  554.       if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
  555.         return 1;
  556.       if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn)))
  557.         return 0;
  558.     }
  559.       prev_code = code;
  560.     }
  561.   return 1;
  562. }
  563.  
  564. /* Legitimize PIC addresses.  If the address is already
  565.    position-independent, we return ORIG.  Newly generated
  566.    position-independent addresses go to REG.  If we need more
  567.    than one register, we lose.  */
  568.  
  569. rtx
  570. legitimize_pic_address (orig, mode, reg)
  571.      rtx orig, reg;
  572.      enum machine_mode mode;
  573. {
  574.   rtx pic_ref = orig;
  575.  
  576.   if (GET_CODE (orig) == SYMBOL_REF)
  577.     {
  578.       if (reg == 0)
  579.     abort ();
  580.  
  581.       if (flag_pic == 2)
  582.     {
  583.       emit_insn (gen_rtx (SET, VOIDmode, reg,
  584.                   gen_rtx (HIGH, Pmode, orig)));
  585.       emit_insn (gen_rtx (SET, VOIDmode, reg,
  586.                   gen_rtx (LO_SUM, Pmode, reg, orig)));
  587.       orig = reg;
  588.     }
  589.       pic_ref = gen_rtx (MEM, Pmode,
  590.              gen_rtx (PLUS, SImode,
  591.                   pic_offset_table_rtx, orig));
  592.       RTX_UNCHANGING_P (pic_ref) = 1;
  593.       emit_move_insn (reg, pic_ref);
  594.       return reg;
  595.     }
  596.   else if (GET_CODE (orig) == CONST)
  597.     {
  598.       rtx base, offset;
  599.  
  600.       if (GET_CODE (XEXP (orig, 0)) == PLUS
  601.       && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
  602.     return orig;
  603.  
  604.       if (reg == 0)
  605.     abort ();
  606.  
  607.       if (GET_CODE (XEXP (orig, 0)) == PLUS)
  608.     {
  609.       base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
  610.       orig = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
  611.                      base == reg ? 0 : reg);
  612.     }
  613.       else abort ();
  614.       if (GET_CODE (orig) == CONST_INT)
  615.     {
  616.       if (SMALL_INT (orig))
  617.         return plus_constant_for_output (base, INTVAL (orig));
  618.       orig = force_reg (Pmode, orig);
  619.     }
  620.       pic_ref = gen_rtx (PLUS, SImode, base, orig);
  621.       /* Likewise, should we set special REG_NOTEs here?  */
  622.     }
  623.   return pic_ref;
  624. }
  625.  
  626. /* Set up PIC-specific rtl.  This should not cause any insns
  627.    to be emitted.  */
  628.  
  629. void
  630. initialize_pic ()
  631. {
  632. }
  633.  
  634. /* Emit special PIC prologues and epilogues.  */
  635.  
  636. void
  637. finalize_pic ()
  638. {
  639.   /* The table we use to reference PIC data.  */
  640.   rtx global_offset_table;
  641.   /* Labels to get the PC in the prologue of this function.  */
  642.   rtx l1 = gen_label_rtx (), l2 = gen_label_rtx ();
  643.   rtx seq;
  644.   int orig_flag_pic = flag_pic;
  645.  
  646.   if (! flag_pic)
  647.     abort ();
  648.  
  649.   flag_pic = 0;
  650.  
  651.   start_sequence ();
  652.  
  653.   emit_label (l1);
  654.   /* Note that we pun calls and jumps here!  */
  655.   emit_jump_insn (gen_rtx (PARALLEL, VOIDmode,
  656.                          gen_rtvec (2,
  657.                                     gen_rtx (SET, VOIDmode, pc_rtx, gen_rtx (LABEL_REF, VOIDmode, l2)),
  658.                                     gen_rtx (SET, VOIDmode, gen_rtx (REG, SImode, 15), gen_rtx (LABEL_REF, VOIDmode, l2)))));
  659.   emit_label (l2);
  660.  
  661.   /* Initialize every time through, since we can't easily
  662.      know this to be permanent.  */
  663.   global_offset_table = gen_rtx (SYMBOL_REF, Pmode, "*__GLOBAL_OFFSET_TABLE_");
  664.   pic_pc_rtx = gen_rtx (CONST, Pmode,
  665.             gen_rtx (MINUS, Pmode,
  666.                  global_offset_table,
  667.                  gen_rtx (CONST, Pmode,
  668.                       gen_rtx (MINUS, Pmode,
  669.                            gen_rtx (LABEL_REF, VOIDmode, l1),
  670.                            pc_rtx))));
  671.  
  672.   emit_insn (gen_rtx (SET, VOIDmode, pic_offset_table_rtx,
  673.               gen_rtx (HIGH, Pmode, pic_pc_rtx)));
  674.   emit_insn (gen_rtx (SET, VOIDmode,
  675.               pic_offset_table_rtx,
  676.               gen_rtx (LO_SUM, Pmode,
  677.                    pic_offset_table_rtx, pic_pc_rtx)));
  678.   emit_insn (gen_rtx (SET, VOIDmode,
  679.               pic_offset_table_rtx,
  680.               gen_rtx (PLUS, SImode,
  681.                    pic_offset_table_rtx, gen_rtx (REG, SImode, 15))));
  682.   /* emit_insn (gen_rtx (ASM_INPUT, VOIDmode, "!#PROLOGUE# 1")); */
  683.   LABEL_PRESERVE_P (l1) = 1;
  684.   LABEL_PRESERVE_P (l2) = 1;
  685.   flag_pic = orig_flag_pic;
  686.  
  687.   seq = gen_sequence ();
  688.   end_sequence ();
  689.   emit_insn_after (seq, get_insns ());
  690.  
  691.   if (obey_regdecls)
  692.     emit_insn (gen_rtx (USE, VOIDmode, pic_offset_table_rtx));
  693. }
  694.  
  695. /* For the SPARC, REG and REG+CONST is cost 0, REG+REG is cost 1,
  696.    and addresses involving symbolic constants are cost 2.
  697.  
  698.    We make REG+REG slightly more expensive because it might keep
  699.    a register live for longer than we might like.
  700.  
  701.    PIC addresses are very expensive.
  702.  
  703.    It is no coincidence that this has the same structure
  704.    as GO_IF_LEGITIMATE_ADDRESS.  */
  705. int
  706. sparc_address_cost (X)
  707.      rtx X;
  708. {
  709. #if 0
  710.   /* Handled before calling here.  */
  711.   if (GET_CODE (X) == REG)
  712.     { return 1; }
  713. #endif
  714.   if (GET_CODE (X) == PLUS)
  715.     {
  716.       if (GET_CODE (XEXP (X, 0)) == REG
  717.       && GET_CODE (XEXP (X, 1)) == REG)
  718.     return 2;
  719.       return 1;
  720.     }
  721.   else if (GET_CODE (X) == LO_SUM)
  722.     return 1;
  723.   else if (GET_CODE (X) == HIGH)
  724.     return 2;
  725.   return 4;
  726. }
  727.  
  728. /* Emit insns to move operands[1] into operands[0].
  729.  
  730.    Return 1 if we have written out everything that needs to be done to
  731.    do the move.  Otherwise, return 0 and the caller will emit the move
  732.    normally.  */
  733.  
  734. int
  735. emit_move_sequence (operands, mode)
  736.      rtx *operands;
  737.      enum machine_mode mode;
  738. {
  739.   register rtx operand0 = operands[0];
  740.   register rtx operand1 = operands[1];
  741.  
  742.   /* Handle most common case first: storing into a register.  */
  743.   if (register_operand (operand0, mode))
  744.     {
  745.       if (register_operand (operand1, mode)
  746.       || (GET_CODE (operand1) == CONST_INT && SMALL_INT (operand1))
  747.       || GET_CODE (operand1) == HIGH
  748.       /* Only `general_operands' can come here, so MEM is ok.  */
  749.       || GET_CODE (operand1) == MEM)
  750.     {
  751.       /* Run this case quickly.  */
  752.       emit_insn (gen_rtx (SET, VOIDmode, operand0, operand1));
  753.       return 1;
  754.     }
  755.     }
  756.   else if (GET_CODE (operand0) == MEM)
  757.     {
  758.       if (register_operand (operand1, mode) || operand1 == const0_rtx)
  759.     {
  760.       /* Run this case quickly.  */
  761.       emit_insn (gen_rtx (SET, VOIDmode, operand0, operand1));
  762.       return 1;
  763.     }
  764.       if (! reload_in_progress)
  765.     {
  766.       operands[0] = validize_mem (operand0);
  767.       operands[1] = operand1 = force_reg (mode, operand1);
  768.     }
  769.     }
  770.  
  771.   /* Simplify the source if we need to.  */
  772.   if (GET_CODE (operand1) != HIGH && immediate_operand (operand1, mode))
  773.     {
  774.       if (flag_pic && symbolic_operand (operand1, mode))
  775.     {
  776.       rtx temp = reload_in_progress ? operand0 : gen_reg_rtx (Pmode);
  777.       operands[1] = legitimize_pic_address (operand1, mode, temp);
  778.     }
  779.       else if (GET_CODE (operand1) == CONST_INT
  780.            ? (! SMALL_INT (operand1)
  781.           && (INTVAL (operand1) & 0x3ff) != 0) : 1)
  782.     {
  783.       rtx temp = reload_in_progress ? operand0 : gen_reg_rtx (mode);
  784.       emit_insn (gen_rtx (SET, VOIDmode, temp,
  785.                   gen_rtx (HIGH, mode, operand1)));
  786.       operands[1] = gen_rtx (LO_SUM, mode, temp, operand1);
  787.     }
  788.     }
  789.  
  790.   /* Now have insn-emit do whatever it normally does.  */
  791.   return 0;
  792. }
  793.  
  794. /* Return the best assembler insn template
  795.    for moving operands[1] into operands[0] as a fullword.  */
  796.  
  797. static char *
  798. singlemove_string (operands)
  799.      rtx *operands;
  800. {
  801.   if (GET_CODE (operands[0]) == MEM)
  802.     {
  803.       if (GET_CODE (operands[1]) != MEM)
  804.     return "st %r1,%0";
  805.       else
  806.     abort ();
  807.     }
  808.   if (GET_CODE (operands[1]) == MEM)
  809.     return "ld %1,%0";
  810.   if (GET_CODE (operands[1]) == CONST_INT
  811.       && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
  812.     {
  813.       int i = INTVAL (operands[1]);
  814.  
  815.       /* If all low order 12 bits are clear, then we only need a single
  816.      sethi insn to load the constant.  */
  817.       if (i & 0x00000FFF)
  818.     return "sethi %%hi(%a1),%0\n\tor %0,%%lo(%a1),%0";
  819.       else
  820.     return "sethi %%hi(%a1),%0";
  821.     }
  822.   return "mov %1,%0";
  823. }
  824.  
  825. /* Output assembler code to perform a doubleword move insn
  826.    with operands OPERANDS.  */
  827.  
  828. char *
  829. output_move_double (operands)
  830.      rtx *operands;
  831. {
  832.   enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
  833.   rtx latehalf[2];
  834.   rtx addreg0 = 0, addreg1 = 0;
  835.  
  836.   /* First classify both operands.  */
  837.  
  838.   if (REG_P (operands[0]))
  839.     optype0 = REGOP;
  840.   else if (offsettable_memref_p (operands[0]))
  841.     optype0 = OFFSOP;
  842.   else if (GET_CODE (operands[0]) == MEM)
  843.     optype0 = MEMOP;
  844.   else
  845.     optype0 = RNDOP;
  846.  
  847.   if (REG_P (operands[1]))
  848.     optype1 = REGOP;
  849.   else if (CONSTANT_P (operands[1]))
  850.     optype1 = CNSTOP;
  851.   else if (offsettable_memref_p (operands[1]))
  852.     optype1 = OFFSOP;
  853.   else if (GET_CODE (operands[1]) == MEM)
  854.     optype1 = MEMOP;
  855.   else
  856.     optype1 = RNDOP;
  857.  
  858.   /* Check for the cases that the operand constraints are not
  859.      supposed to allow to happen.  Abort if we get one,
  860.      because generating code for these cases is painful.  */
  861.  
  862.   if (optype0 == RNDOP || optype1 == RNDOP)
  863.     abort ();
  864.  
  865.   /* If an operand is an unoffsettable memory ref, find a register
  866.      we can increment temporarily to make it refer to the second word.  */
  867.  
  868.   if (optype0 == MEMOP)
  869.     addreg0 = find_addr_reg (XEXP (operands[0], 0));
  870.  
  871.   if (optype1 == MEMOP)
  872.     addreg1 = find_addr_reg (XEXP (operands[1], 0));
  873.  
  874.   /* Ok, we can do one word at a time.
  875.      Normally we do the low-numbered word first,
  876.      but if either operand is autodecrementing then we
  877.      do the high-numbered word first.
  878.  
  879.      In either case, set up in LATEHALF the operands to use
  880.      for the high-numbered word and in some cases alter the
  881.      operands in OPERANDS to be suitable for the low-numbered word.  */
  882.  
  883.   if (optype0 == REGOP)
  884.     latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
  885.   else if (optype0 == OFFSOP)
  886.     latehalf[0] = adj_offsettable_operand (operands[0], 4);
  887.   else
  888.     latehalf[0] = operands[0];
  889.  
  890.   if (optype1 == REGOP)
  891.     latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
  892.   else if (optype1 == OFFSOP)
  893.     latehalf[1] = adj_offsettable_operand (operands[1], 4);
  894.   else if (optype1 == CNSTOP)
  895.     {
  896.       if (GET_CODE (operands[1]) == CONST_DOUBLE)
  897.     {
  898.       latehalf[1] = gen_rtx (CONST_INT, VOIDmode,
  899.                  CONST_DOUBLE_HIGH (operands[1]));
  900.       operands[1] = gen_rtx (CONST_INT, VOIDmode,
  901.                  CONST_DOUBLE_LOW (operands[1]));
  902.     }
  903.       else if (CONSTANT_P (operands[1]))
  904.     latehalf[1] = const0_rtx;
  905.     }
  906.   else
  907.     latehalf[1] = operands[1];
  908.  
  909.   /* If the first move would clobber the source of the second one,
  910.      do them in the other order.
  911.  
  912.      RMS says "This happens only for registers;
  913.      such overlap can't happen in memory unless the user explicitly
  914.      sets it up, and that is an undefined circumstance."
  915.  
  916.      but it happens on the sparc when loading parameter registers,
  917.      so I am going to define that circumstance, and make it work
  918.      as expected.  */
  919.  
  920.   /* Easy case: try moving both words at once.  */
  921.   /* First check for moving between an even/odd register pair
  922.      and a memory location.  */
  923.   if ((optype0 == REGOP && optype1 != REGOP && optype1 != CNSTOP
  924.        && (REGNO (operands[0]) & 1) == 0)
  925.       || (optype0 != REGOP && optype1 != CNSTOP && optype1 == REGOP
  926.       && (REGNO (operands[1]) & 1) == 0))
  927.     {
  928.       rtx op1, op2;
  929.       rtx base = 0, offset = const0_rtx;
  930.  
  931.       /* OP1 gets the register pair, and OP2 gets the memory address.  */
  932.       if (optype0 == REGOP)
  933.     op1 = operands[0], op2 = operands[1];
  934.       else
  935.     op1 = operands[1], op2 = operands[0];
  936.  
  937.       /* Now see if we can trust the address to be 8-byte aligned.  */
  938.       /* Trust global variables.  */
  939.  
  940.       if (GET_CODE (op2) == LO_SUM)
  941.     {
  942.       operands[0] = op1;
  943.       operands[1] = op2;
  944.  
  945.       if (final_sequence)
  946.         abort ();
  947.       return "ldd %1,%0";
  948.     }
  949.  
  950.       if (GET_CODE (XEXP (op2, 0)) == PLUS)
  951.     {
  952.       rtx temp = XEXP (op2, 0);
  953.       if (GET_CODE (XEXP (temp, 0)) == REG)
  954.         base = XEXP (temp, 0), offset = XEXP (temp, 1);
  955.       else if (GET_CODE (XEXP (temp, 1)) == REG)
  956.         base = XEXP (temp, 1), offset = XEXP (temp, 0);
  957.     }
  958.  
  959.       /* Trust round enough offsets from the stack or frame pointer.  */
  960.       if (base
  961.       && (REGNO (base) == FRAME_POINTER_REGNUM
  962.           || REGNO (base) == STACK_POINTER_REGNUM))
  963.     {
  964.       if (GET_CODE (offset) == CONST_INT
  965.           && (INTVAL (offset) & 0x7) == 0)
  966.         {
  967.           if (op1 == operands[0])
  968.         return "ldd %1,%0";
  969.           else
  970.         return "std %1,%0";
  971.         }
  972.     }
  973.       /* We know structs not on the stack are properly aligned.  Since a
  974.      double asks for 8-byte alignment, we know it must have got that
  975.      if it is in a struct.  But a DImode need not be 8-byte aligned,
  976.      because it could be a struct containing two ints or pointers.  */
  977.       else if (GET_CODE (operands[1]) == MEM
  978.            && GET_MODE (operands[1]) == DFmode
  979.            && (CONSTANT_P (XEXP (operands[1], 0))
  980.            /* Let user ask for it anyway.  */
  981.            || TARGET_ALIGN))
  982.     return "ldd %1,%0";
  983.       else if (GET_CODE (operands[0]) == MEM
  984.            && GET_MODE (operands[0]) == DFmode
  985.            && (CONSTANT_P (XEXP (operands[0], 0))
  986.            || TARGET_ALIGN))
  987.     return "std %1,%0";
  988.     }
  989.  
  990.   if (optype0 == REGOP && optype1 == REGOP
  991.       && REGNO (operands[0]) == REGNO (latehalf[1]))
  992.     {
  993.       /* Make any unoffsettable addresses point at high-numbered word.  */
  994.       if (addreg0)
  995.     output_asm_insn ("add %0,0x4,%0", &addreg0);
  996.       if (addreg1)
  997.     output_asm_insn ("add %0,0x4,%0", &addreg1);
  998.  
  999.       /* Do that word.  */
  1000.       output_asm_insn (singlemove_string (latehalf), latehalf);
  1001.  
  1002.       /* Undo the adds we just did.  */
  1003.       if (addreg0)
  1004.     output_asm_insn ("add %0,-0x4,%0", &addreg0);
  1005.       if (addreg1)
  1006.     output_asm_insn ("add %0,-0x4,%0", &addreg0);
  1007.  
  1008.       /* Do low-numbered word.  */
  1009.       return singlemove_string (operands);
  1010.     }
  1011.   else if (optype0 == REGOP && optype1 != REGOP
  1012.        && reg_overlap_mentioned_p (operands[0], operands[1]))
  1013.     {
  1014.       /* Do the late half first.  */
  1015.       output_asm_insn (singlemove_string (latehalf), latehalf);
  1016.       /* Then clobber.  */
  1017.       return singlemove_string (operands);
  1018.     }
  1019.  
  1020.   /* Normal case: do the two words, low-numbered first.  */
  1021.  
  1022.   output_asm_insn (singlemove_string (operands), operands);
  1023.  
  1024.   /* Make any unoffsettable addresses point at high-numbered word.  */
  1025.   if (addreg0)
  1026.     output_asm_insn ("add %0,0x4,%0", &addreg0);
  1027.   if (addreg1)
  1028.     output_asm_insn ("add %0,0x4,%0", &addreg1);
  1029.  
  1030.   /* Do that word.  */
  1031.   output_asm_insn (singlemove_string (latehalf), latehalf);
  1032.  
  1033.   /* Undo the adds we just did.  */
  1034.   if (addreg0)
  1035.     output_asm_insn ("add %0,-0x4,%0", &addreg0);
  1036.   if (addreg1)
  1037.     output_asm_insn ("add %0,-0x4,%0", &addreg1);
  1038.  
  1039.   return "";
  1040. }
  1041.  
  1042. char *
  1043. output_fp_move_double (operands)
  1044.      rtx *operands;
  1045. {
  1046.   rtx addr;
  1047.  
  1048.   if (FP_REG_P (operands[0]))
  1049.     {
  1050.       if (FP_REG_P (operands[1]))
  1051.     return "fmovs %1,%0\n\tfmovs %R1,%R0";
  1052.       if (GET_CODE (operands[1]) == REG)
  1053.     {
  1054.       if ((REGNO (operands[1]) & 1) == 0)
  1055.         return "std %1,[%@-8]\n\tldd [%@-8],%0";
  1056.       else
  1057.         return "st %R1,[%@-4]\n\tst %1,[%@-8]\n\tldd [%@-8],%0";
  1058.     }
  1059.       addr = XEXP (operands[1], 0);
  1060.  
  1061.       /* Use ldd if known to be aligned.  */
  1062.       if (TARGET_ALIGN
  1063.       || (GET_CODE (addr) == PLUS
  1064.           && (((XEXP (addr, 0) == frame_pointer_rtx
  1065.             || XEXP (addr, 0) == stack_pointer_rtx)
  1066.            && GET_CODE (XEXP (addr, 1)) == CONST_INT
  1067.            && (INTVAL (XEXP (addr, 1)) & 0x7) == 0)
  1068.           /* Arrays are known to be aligned,
  1069.              and reg+reg addresses are used (on this machine)
  1070.              only for array accesses.  */
  1071.           || (REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))))
  1072.       || (GET_MODE (operands[0]) == DFmode
  1073.           && (GET_CODE (addr) == LO_SUM || CONSTANT_P (addr))))
  1074.     return "ldd %1,%0";
  1075.  
  1076.       /* Otherwise use two ld insns.  */
  1077.       operands[2]
  1078.     = gen_rtx (MEM, GET_MODE (operands[1]),
  1079.            plus_constant_for_output (addr, 4));
  1080.     return "ld %1,%0\n\tld %2,%R0";
  1081.     }
  1082.   else if (FP_REG_P (operands[1]))
  1083.     {
  1084.       if (GET_CODE (operands[0]) == REG)
  1085.     {
  1086.       if ((REGNO (operands[0]) & 1) == 0)
  1087.         return "std %1,[%@-8]\n\tldd [%@-8],%0";
  1088.       else
  1089.         return "std %1,[%@-8]\n\tld [%@-4],%R0\n\tld [%@-8],%0";
  1090.     }
  1091.       addr = XEXP (operands[0], 0);
  1092.  
  1093.       /* Use std if we can be sure it is well-aligned.  */
  1094.       if (TARGET_ALIGN
  1095.       || (GET_CODE (addr) == PLUS
  1096.           && (((XEXP (addr, 0) == frame_pointer_rtx
  1097.             || XEXP (addr, 0) == stack_pointer_rtx)
  1098.            && GET_CODE (XEXP (addr, 1)) == CONST_INT
  1099.            && (INTVAL (XEXP (addr, 1)) & 0x7) == 0)
  1100.           /* Arrays are known to be aligned,
  1101.              and reg+reg addresses are used (on this machine)
  1102.              only for array accesses.  */
  1103.           || (REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))))
  1104.       || (GET_MODE (operands[1]) == DFmode
  1105.           && (GET_CODE (addr) == LO_SUM || CONSTANT_P (addr))))
  1106.     return "std %1,%0";
  1107.  
  1108.       /* Otherwise use two st insns.  */
  1109.       operands[2]
  1110.     = gen_rtx (MEM, GET_MODE (operands[0]),
  1111.            plus_constant_for_output (addr, 4));
  1112.       return "st %r1,%0\n\tst %R1,%2";
  1113.     }
  1114.   else abort ();
  1115. }
  1116.  
  1117. /* Return a REG that occurs in ADDR with coefficient 1.
  1118.    ADDR can be effectively incremented by incrementing REG.  */
  1119.  
  1120. static rtx
  1121. find_addr_reg (addr)
  1122.      rtx addr;
  1123. {
  1124.   while (GET_CODE (addr) == PLUS)
  1125.     {
  1126.       if (GET_CODE (XEXP (addr, 0)) == REG)
  1127.     addr = XEXP (addr, 0);
  1128.       else if (GET_CODE (XEXP (addr, 1)) == REG)
  1129.     addr = XEXP (addr, 1);
  1130.       else if (CONSTANT_P (XEXP (addr, 0)))
  1131.     addr = XEXP (addr, 1);
  1132.       else if (CONSTANT_P (XEXP (addr, 1)))
  1133.     addr = XEXP (addr, 0);
  1134.       else
  1135.     abort ();
  1136.     }
  1137.   if (GET_CODE (addr) == REG)
  1138.     return addr;
  1139.   abort ();
  1140. }
  1141.  
  1142. void
  1143. output_sized_memop (opname, mode, signedp)
  1144.      char *opname;
  1145.      enum machine_mode mode;
  1146.      int signedp;
  1147. {
  1148.   static char *ld_size_suffix_u[] = { "ub", "uh", "", "?", "d" };
  1149.   static char *ld_size_suffix_s[] = { "sb", "sh", "", "?", "d" };
  1150.   static char *st_size_suffix[] = { "b", "h", "", "?", "d" };
  1151.   char **opnametab, *modename;
  1152.  
  1153.   if (opname[0] == 'l')
  1154.     if (signedp)
  1155.       opnametab = ld_size_suffix_s;
  1156.     else
  1157.       opnametab = ld_size_suffix_u;
  1158.   else
  1159.     opnametab = st_size_suffix;
  1160.   modename = opnametab[GET_MODE_SIZE (mode) >> 1];
  1161.  
  1162.   fprintf (asm_out_file, "\t%s%s", opname, modename);
  1163. }
  1164.  
  1165. void
  1166. output_move_with_extension (operands)
  1167.      rtx *operands;
  1168. {
  1169.   if (GET_MODE (operands[2]) == HImode)
  1170.     output_asm_insn ("sll %2,0x10,%0", operands);
  1171.   else if (GET_MODE (operands[2]) == QImode)
  1172.     output_asm_insn ("sll %2,0x18,%0", operands);
  1173.   else
  1174.     abort ();
  1175. }
  1176.  
  1177. /* Load the address specified by OPERANDS[3] into the register
  1178.    specified by OPERANDS[0].
  1179.  
  1180.    OPERANDS[3] may be the result of a sum, hence it could either be:
  1181.  
  1182.    (1) CONST
  1183.    (2) REG
  1184.    (2) REG + CONST_INT
  1185.    (3) REG + REG + CONST_INT
  1186.    (4) REG + REG  (special case of 3).
  1187.  
  1188.    Note that (3) is not a legitimate address.
  1189.    All cases are handled here.  */
  1190.  
  1191. void
  1192. output_load_address (operands)
  1193.      rtx *operands;
  1194. {
  1195.   rtx base, offset;
  1196.  
  1197.   if (CONSTANT_P (operands[3]))
  1198.     {
  1199.       output_asm_insn ("set %3,%0", operands);
  1200.       return;
  1201.     }
  1202.  
  1203.   if (REG_P (operands[3]))
  1204.     {
  1205.       if (REGNO (operands[0]) != REGNO (operands[3]))
  1206.     output_asm_insn ("mov %3,%0", operands);
  1207.       return;
  1208.     }
  1209.  
  1210.   if (GET_CODE (operands[3]) != PLUS)
  1211.     abort ();
  1212.  
  1213.   base = XEXP (operands[3], 0);
  1214.   offset = XEXP (operands[3], 1);
  1215.  
  1216.   if (GET_CODE (base) == CONST_INT)
  1217.     {
  1218.       rtx tmp = base;
  1219.       base = offset;
  1220.       offset = tmp;
  1221.     }
  1222.  
  1223.   if (GET_CODE (offset) != CONST_INT)
  1224.     {
  1225.       /* Operand is (PLUS (REG) (REG)).  */
  1226.       base = operands[3];
  1227.       offset = const0_rtx;
  1228.     }
  1229.  
  1230.   if (REG_P (base))
  1231.     {
  1232.       operands[6] = base;
  1233.       operands[7] = offset;
  1234.       if (SMALL_INT (offset))
  1235.     output_asm_insn ("add %6,%7,%0", operands);
  1236.       else
  1237.     output_asm_insn ("set %7,%0\n\tadd %0,%6,%0", operands);
  1238.     }
  1239.   else if (GET_CODE (base) == PLUS)
  1240.     {
  1241.       operands[6] = XEXP (base, 0);
  1242.       operands[7] = XEXP (base, 1);
  1243.       operands[8] = offset;
  1244.  
  1245.       if (SMALL_INT (offset))
  1246.     output_asm_insn ("add %6,%7,%0\n\tadd %0,%8,%0", operands);
  1247.       else
  1248.     output_asm_insn ("set %8,%0\n\tadd %0,%6,%0\n\tadd %0,%7,%0", operands);
  1249.     }
  1250.   else
  1251.     abort ();
  1252. }
  1253.  
  1254. /* Output code to place a size count SIZE in register REG.
  1255.    ALIGN is the size of the unit of transfer.
  1256.  
  1257.    Because block moves are pipelined, we don't include the
  1258.    first element in the transfer of SIZE to REG.  */
  1259.  
  1260. static void
  1261. output_size_for_block_move (size, reg, align)
  1262.      rtx size, reg;
  1263.      rtx align;
  1264. {
  1265.   rtx xoperands[3];
  1266.  
  1267.   xoperands[0] = reg;
  1268.   xoperands[1] = size;
  1269.   xoperands[2] = align;
  1270.   if (GET_CODE (size) == REG)
  1271.     output_asm_insn ("sub %1,%2,%0", xoperands);
  1272.   else
  1273.     {
  1274.       xoperands[1]
  1275.     = gen_rtx (CONST_INT, VOIDmode, INTVAL (size) - INTVAL (align));
  1276.       output_asm_insn ("set %1,%0", xoperands);
  1277.     }
  1278. }
  1279.  
  1280. /* Emit code to perform a block move.
  1281.  
  1282.    OPERANDS[0] is the destination.
  1283.    OPERANDS[1] is the source.
  1284.    OPERANDS[2] is the size.
  1285.    OPERANDS[3] is the alignment safe to use.
  1286.    OPERANDS[4] is a register we can safely clobber as a temp.  */
  1287.  
  1288. char *
  1289. output_block_move (operands)
  1290.      rtx *operands;
  1291. {
  1292.   /* A vector for our computed operands.  Note that load_output_address
  1293.      makes use of (and can clobber) up to the 8th element of this vector.  */
  1294.   rtx xoperands[10];
  1295.   rtx zoperands[10];
  1296.   static int movstrsi_label = 0;
  1297.   int i;
  1298.   rtx temp1 = operands[4];
  1299.   rtx sizertx = operands[2];
  1300.   rtx alignrtx = operands[3];
  1301.   int align = INTVAL (alignrtx);
  1302.  
  1303.   xoperands[0] = operands[0];
  1304.   xoperands[1] = operands[1];
  1305.   xoperands[2] = temp1;
  1306.  
  1307.   /* We can't move more than this many bytes at a time
  1308.      because we have only one register to move them through.  */
  1309.   if (align > GET_MODE_SIZE (GET_MODE (temp1)))
  1310.     {
  1311.       align = GET_MODE_SIZE (GET_MODE (temp1));
  1312.       alignrtx = gen_rtx (CONST_INT, VOIDmode, GET_MODE_SIZE (GET_MODE (temp1)));
  1313.     }
  1314.  
  1315.   /* If the size isn't known to be a multiple of the alignment,
  1316.      we have to do it in smaller pieces.  If we could determine that
  1317.      the size was a multiple of 2 (or whatever), we could be smarter
  1318.      about this.  */
  1319.   if (GET_CODE (sizertx) != CONST_INT)
  1320.     align = 1;
  1321.   else
  1322.     {
  1323.       int size = INTVAL (sizertx);
  1324.       while (size % align)
  1325.     align >>= 1;
  1326.     }
  1327.  
  1328.   if (align != INTVAL (alignrtx))
  1329.     alignrtx = gen_rtx (CONST_INT, VOIDmode, align);
  1330.  
  1331.   /* Recognize special cases of block moves.  These occur
  1332.      when GNU C++ is forced to treat something as BLKmode
  1333.      to keep it in memory, when its mode could be represented
  1334.      with something smaller.
  1335.  
  1336.      We cannot do this for global variables, since we don't know
  1337.      what pages they don't cross.  Sigh.  */
  1338.   if (GET_CODE (sizertx) == CONST_INT && INTVAL (sizertx) <= 16)
  1339.     {
  1340.       int size = INTVAL (sizertx);
  1341.  
  1342.       if (align == 1)
  1343.     {
  1344.       if (memory_address_p (QImode,
  1345.                 plus_constant_for_output (xoperands[0], size))
  1346.           && memory_address_p (QImode,
  1347.                    plus_constant_for_output (xoperands[1],
  1348.                                  size)))
  1349.         {
  1350.           /* We will store different integers into this particular RTX.  */
  1351.           xoperands[2] = rtx_alloc (CONST_INT);
  1352.           PUT_MODE (xoperands[2], VOIDmode);
  1353.           for (i = size-1; i >= 0; i--)
  1354.         {
  1355.           INTVAL (xoperands[2]) = i;
  1356.           output_asm_insn ("ldub [%a1+%2],%%g1\n\tstb %%g1,[%a0+%2]",
  1357.                    xoperands);
  1358.         }
  1359.           return "";
  1360.         }
  1361.     }
  1362.       else if (align == 2)
  1363.     {
  1364.       if (memory_address_p (HImode,
  1365.                 plus_constant_for_output (xoperands[0], size))
  1366.           && memory_address_p (HImode,
  1367.                    plus_constant_for_output (xoperands[1],
  1368.                                  size)))
  1369.         {
  1370.           /* We will store different integers into this particular RTX.  */
  1371.           xoperands[2] = rtx_alloc (CONST_INT);
  1372.           PUT_MODE (xoperands[2], VOIDmode);
  1373.           for (i = (size>>1)-1; i >= 0; i--)
  1374.         {
  1375.           INTVAL (xoperands[2]) = i<<1;
  1376.           output_asm_insn ("lduh [%a1+%2],%%g1\n\tsth %%g1,[%a0+%2]",
  1377.                    xoperands);
  1378.         }
  1379.           return "";
  1380.         }
  1381.     }
  1382.       else
  1383.     {
  1384.       if (memory_address_p (SImode,
  1385.                 plus_constant_for_output (xoperands[0], size))
  1386.           && memory_address_p (SImode,
  1387.                    plus_constant_for_output (xoperands[1],
  1388.                                  size)))
  1389.         {
  1390.           /* We will store different integers into this particular RTX.  */
  1391.           xoperands[2] = rtx_alloc (CONST_INT);
  1392.           PUT_MODE (xoperands[2], VOIDmode);
  1393.           for (i = (size>>2)-1; i >= 0; i--)
  1394.         {
  1395.           INTVAL (xoperands[2]) = i<<2;
  1396.           output_asm_insn ("ld [%a1+%2],%%g1\n\tst %%g1,[%a0+%2]",
  1397.                    xoperands);
  1398.         }
  1399.           return "";
  1400.         }
  1401.     }
  1402.     }
  1403.  
  1404.   /* This is the size of the transfer.
  1405.      Either use the register which already contains the size,
  1406.      or use a free register (used by no operands).
  1407.      Also emit code to decrement the size value by ALIGN.  */
  1408.   output_size_for_block_move (sizertx, temp1, alignrtx);
  1409.  
  1410.   zoperands[0] = operands[0];
  1411.   zoperands[3] = plus_constant_for_output (operands[0], align);
  1412.   output_load_address (zoperands);
  1413.  
  1414.   xoperands[3] = gen_rtx (CONST_INT, VOIDmode, movstrsi_label++);
  1415.   xoperands[4] = gen_rtx (CONST_INT, VOIDmode, align);
  1416.  
  1417. #ifdef NO_UNDERSCORES
  1418.   if (align == 1)
  1419.     output_asm_insn ("\n.Lm%3:\n\tldub [%1+%2],%%g1\n\tsubcc %2,%4,%2\n\tbge .Lm%3\n\tstb %%g1,[%0+%2]", xoperands);
  1420.   else if (align == 2)
  1421.     output_asm_insn ("\n.Lm%3:\n\tlduh [%1+%2],%%g1\n\tsubcc %2,%4,%2\n\tbge .Lm%3\n\tsth %%g1,[%0+%2]", xoperands);
  1422.   else
  1423.     output_asm_insn ("\n.Lm%3:\n\tld [%1+%2],%%g1\n\tsubcc %2,%4,%2\n\tbge .Lm%3\n\tst %%g1,[%0+%2]", xoperands);
  1424.   return "";
  1425. #else
  1426.   if (align == 1)
  1427.     output_asm_insn ("\nLm%3:\n\tldub [%1+%2],%%g1\n\tsubcc %2,%4,%2\n\tbgeu Lm%3\n\tstb %%g1,[%0+%2]", xoperands);
  1428.   else if (align == 2)
  1429.     output_asm_insn ("\nLm%3:\n\tlduh [%1+%2],%%g1\n\tsubcc %2,%4,%2\n\tbgeu Lm%3\n\tsth %%g1,[%0+%2]", xoperands);
  1430.   else
  1431.     output_asm_insn ("\nLm%3:\n\tld [%1+%2],%%g1\n\tsubcc %2,%4,%2\n\tbgeu Lm%3\n\tst %%g1,[%0+%2]", xoperands);
  1432.   return "";
  1433. #endif
  1434. }
  1435.  
  1436. /* Output reasonable peephole for set-on-condition-code insns.
  1437.    Note that these insns assume a particular way of defining
  1438.    labels.  Therefore, *both* tm-sparc.h and this function must
  1439.    be changed if a new syntax is needed.    */
  1440.  
  1441. char *
  1442. output_scc_insn (operands, insn)
  1443.      rtx operands[];
  1444.      rtx insn;
  1445. {
  1446.   static char string[100];
  1447.   rtx label = 0, next = insn;
  1448.   int need_label = 0;
  1449.  
  1450.   /* Try doing a jump optimization which jump.c can't do for us
  1451.      because we did not expose that setcc works by using branches.
  1452.  
  1453.      If this scc insn is followed by an unconditional branch, then have
  1454.      the jump insn emitted here jump to that location, instead of to
  1455.      the end of the scc sequence as usual.  */
  1456.   do
  1457.     {
  1458.       if (GET_CODE (next) == CODE_LABEL)
  1459.     label = next;
  1460.       next = NEXT_INSN (next);
  1461.       if (next == 0)
  1462.     break;
  1463.     }
  1464.   while (GET_CODE (next) == NOTE || GET_CODE (next) == CODE_LABEL);
  1465.  
  1466.   if (next && GET_CODE (next) == JUMP_INSN
  1467.       && simplejump_p (next))
  1468.     label = JUMP_LABEL (next);
  1469.   /* If not optimizing, jump label fields are not set.  To be safe, always
  1470.      check here to whether label is still zero.  */
  1471.   if (label == 0)
  1472.     {
  1473.       label = gen_label_rtx ();
  1474.       need_label = 1;
  1475.     }
  1476.  
  1477.   LABEL_NUSES (label) += 1;
  1478.  
  1479.   operands[2] = label;
  1480.  
  1481.   /* If we are in a delay slot, assume it is the delay slot of an fpcc
  1482.      insn since our type isn't allowed anywhere else.  */
  1483.  
  1484.   /* The fastest way to emit code for this is an annulled branch followed
  1485.      by two move insns.  This will take two cycles if the branch is taken,
  1486.      and three cycles if the branch is not taken.
  1487.  
  1488.      However, if we are in the delay slot of another branch, this won't work,
  1489.      because we can't put a branch in the delay slot of another branch.
  1490.      The above sequence would effectively take 3 or 4 cycles respectively
  1491.      since a no op would have be inserted between the two branches.
  1492.      In this case, we want to emit a move, annulled branch, and then the
  1493.      second move.  This sequence always takes 3 cycles, and hence is faster
  1494.      when we are in a branch delay slot.  */
  1495.  
  1496.   if (final_sequence)
  1497.     {
  1498.       strcpy (string, "mov 0,%0\n\t");
  1499.       strcat (string, output_cbranch (operands[1], 2, 0, 1, 0));
  1500.       strcat (string, "\n\tmov 1,%0");
  1501.     }
  1502.   else
  1503.     {
  1504.       strcpy (string, output_cbranch (operands[1], 2, 0, 1, 0));
  1505.       strcat (string, "\n\tmov 1,%0\n\tmov 0,%0");
  1506.     }
  1507.  
  1508.   if (need_label)
  1509.     strcat (string, "\n%l2:");
  1510.  
  1511.   return string;
  1512. }
  1513.  
  1514. /* Vectors to keep interesting information about registers where
  1515.    it can easily be got.  */
  1516.  
  1517. /* Modes for condition codes.  */
  1518. #define C_MODES        \
  1519.   ((1 << (int) CCmode) | (1 << (int) CC_NOOVmode) | (1 << (int) CCFPmode))
  1520.  
  1521. /* Modes for single-word (and smaller) quantities.  */
  1522. #define S_MODES                        \
  1523.  (~C_MODES                        \
  1524.   & ~ ((1 << (int) DImode) | (1 << (int) TImode)    \
  1525.       | (1 << (int) DFmode) | (1 << (int) TFmode)))
  1526.  
  1527. /* Modes for double-word (and smaller) quantities.  */
  1528. #define D_MODES                    \
  1529.   (~C_MODES                    \
  1530.    & ~ ((1 << (int) TImode) | (1 << (int) TFmode)))
  1531.  
  1532. /* Modes for quad-word quantities.  */
  1533. #define T_MODES (~C_MODES)
  1534.  
  1535. /* Modes for single-float quantities.  */
  1536. #define SF_MODES ((1 << (int) SFmode))
  1537.  
  1538. /* Modes for double-float quantities.  */
  1539. #define DF_MODES (SF_MODES | (1 << (int) DFmode) | (1 << (int) SCmode))
  1540.  
  1541. /* Modes for quad-float quantities.  */
  1542. #define TF_MODES (DF_MODES | (1 << (int) TFmode) | (1 << (int) DCmode))
  1543.  
  1544. /* Value is 1 if register/mode pair is acceptable on sparc.
  1545.    The funny mixture of D and T modes is because integer operations
  1546.    do not specially operate on tetra quantities, so non-quad-aligned
  1547.    registers can hold quadword quantities (except %o4 and %i4 because
  1548.    they cross fixed registers.  */
  1549. short hard_regno_mode_ok[] = {
  1550.   C_MODES, S_MODES, T_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES,
  1551.   T_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES, D_MODES, S_MODES,
  1552.   T_MODES, S_MODES, T_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES,
  1553.   T_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES, D_MODES, S_MODES,
  1554.  
  1555.   TF_MODES, SF_MODES, DF_MODES, SF_MODES, TF_MODES, SF_MODES, DF_MODES, SF_MODES,
  1556.   TF_MODES, SF_MODES, DF_MODES, SF_MODES, TF_MODES, SF_MODES, DF_MODES, SF_MODES,
  1557.   TF_MODES, SF_MODES, DF_MODES, SF_MODES, TF_MODES, SF_MODES, DF_MODES, SF_MODES,
  1558.   TF_MODES, SF_MODES, DF_MODES, SF_MODES, TF_MODES, SF_MODES, DF_MODES, SF_MODES};
  1559.  
  1560. #ifdef __GNUC__
  1561. inline
  1562. #endif
  1563. static int
  1564. save_regs (file, low, high, base, offset, n_fregs)
  1565.      FILE *file;
  1566.      int low, high;
  1567.      char *base;
  1568.      int offset;
  1569.      int n_fregs;
  1570. {
  1571.   int i;
  1572.  
  1573.   for (i = low; i < high; i += 2)
  1574.     {
  1575.       if (regs_ever_live[i] && ! call_used_regs[i])
  1576.     if (regs_ever_live[i+1] && ! call_used_regs[i+1])
  1577.       fprintf (file, "\tstd %s,[%s+%d]\n",
  1578.            reg_names[i], base, offset + 4 * n_fregs),
  1579.       n_fregs += 2;
  1580.     else
  1581.       fprintf (file, "\tst %s,[%s+%d]\n",
  1582.            reg_names[i], base, offset + 4 * n_fregs),
  1583.       n_fregs += 2;
  1584.       else if (regs_ever_live[i+1] && ! call_used_regs[i+1])
  1585.     fprintf (file, "\tst %s,[%s+%d]\n",
  1586.          reg_names[i+1], base, offset + 4 * n_fregs),
  1587.     n_fregs += 2;
  1588.     }
  1589.   return n_fregs;
  1590. }
  1591.  
  1592. #ifdef __GNUC__
  1593. inline
  1594. #endif
  1595. static int
  1596. restore_regs (file, low, high, base, offset, n_fregs)
  1597.      FILE *file;
  1598.      int low, high;
  1599.      char *base;
  1600.      int offset;
  1601. {
  1602.   int i;
  1603.  
  1604.   for (i = low; i < high; i += 2)
  1605.     {
  1606.       if (regs_ever_live[i] && ! call_used_regs[i])
  1607.     if (regs_ever_live[i+1] && ! call_used_regs[i+1])
  1608.       fprintf (file, "\tldd [%s+%d], %s\n",
  1609.            base, offset + 4 * n_fregs, reg_names[i]),
  1610.       n_fregs += 2;
  1611.     else
  1612.       fprintf (file, "\tld [%s+%d],%s\n",
  1613.            base, offset + 4 * n_fregs, reg_names[i]),
  1614.       n_fregs += 2;
  1615.       else if (regs_ever_live[i+1] && ! call_used_regs[i+1])
  1616.     fprintf (file, "\tld [%s+%d],%s\n",
  1617.          base, offset + 4 * n_fregs, reg_names[i+1]),
  1618.     n_fregs += 2;
  1619.     }
  1620.   return n_fregs;
  1621. }
  1622.  
  1623. /* Static variables we want to share between prologue and epilogue.  */
  1624.  
  1625. /* Number of live floating point registers needed to be saved.  */
  1626. static int num_fregs;
  1627.  
  1628. /* Nonzero if any floating point register was ever used.  */
  1629. static int fregs_ever_live;
  1630.  
  1631. int
  1632. compute_frame_size (size, leaf_function)
  1633.      int size;
  1634.      int leaf_function;
  1635. {
  1636.   int fregs_ever_live = 0;
  1637.   int n_fregs = 0, i;
  1638.   int outgoing_args_size = (current_function_outgoing_args_size
  1639.                 + REG_PARM_STACK_SPACE (current_function_decl));
  1640.  
  1641.   apparent_fsize = ((size) + 7 - STARTING_FRAME_OFFSET) & -8;
  1642.   for (i = 32; i < FIRST_PSEUDO_REGISTER; i += 2)
  1643.     fregs_ever_live |= regs_ever_live[i]|regs_ever_live[i+1];
  1644.  
  1645.   if (TARGET_EPILOGUE && fregs_ever_live)
  1646.     {
  1647.       for (i = 32; i < FIRST_PSEUDO_REGISTER; i += 2)
  1648.     if ((regs_ever_live[i] && ! call_used_regs[i])
  1649.         || (regs_ever_live[i+1] && ! call_used_regs[i+1]))
  1650.       n_fregs += 2;
  1651.     }
  1652.  
  1653.   /* Set up values for use in `function_epilogue'.  */
  1654.   num_fregs = n_fregs;
  1655.  
  1656.   apparent_fsize += (outgoing_args_size+7) & -8;
  1657.   if (leaf_function && n_fregs == 0
  1658.       && apparent_fsize == (REG_PARM_STACK_SPACE (current_function_decl)
  1659.                 - STARTING_FRAME_OFFSET))
  1660.     apparent_fsize = 0;
  1661.  
  1662.   actual_fsize = (leaf_function ? 0 : 64+8) + apparent_fsize + n_fregs*4;
  1663.  
  1664.   return actual_fsize;
  1665. }
  1666.  
  1667. void
  1668. output_function_prologue (file, size, leaf_function)
  1669.      FILE *file;
  1670.      int size;
  1671. {
  1672.   extern char call_used_regs[];
  1673.   extern int current_function_outgoing_args_size;
  1674.   extern char *frame_base_name;
  1675.  
  1676.   if (leaf_function)
  1677.     frame_base_name = "%sp+80";
  1678.   else
  1679.     frame_base_name = "%fp";
  1680.  
  1681.   actual_fsize = compute_frame_size (size, leaf_function);
  1682.  
  1683.   fprintf (file, "\t!#PROLOGUE# 0\n");
  1684.   if (actual_fsize == 0) /* do nothing.  */ ;
  1685.   else if (actual_fsize < 4096)
  1686.     {
  1687.       if (! leaf_function)
  1688.     fprintf (file, "\tsave %%sp,-%d,%%sp\n", actual_fsize);
  1689.       else
  1690.     fprintf (file, "\tadd %%sp,-%d,%%sp\n", actual_fsize);
  1691.     }
  1692.   else if (! leaf_function)
  1693.     {
  1694.       /* Need to use actual_fsize, since we are also allocating space for
  1695.      our callee (and our own register save area).  */
  1696.       fprintf (file, "\tsethi %%hi(%d),%%g1\n\tor %%g1,%%lo(%d),%%g1\n",
  1697.            -actual_fsize, -actual_fsize);
  1698.       fprintf (file, "\tsave %%sp,%%g1,%%sp\n");
  1699.     }
  1700.   else
  1701.     {
  1702.       /* Put pointer to parameters into %g4, and allocate
  1703.      frame space using result computed into %g1.  actual_fsize
  1704.      used instead of apparent_fsize for reasons stated above.  */
  1705.       abort ();
  1706.  
  1707.       fprintf (file, "\tsethi %%hi(%d),%%g1\n\tor %%g1,%%lo(%d),%%g1\n",
  1708.            -actual_fsize, -actual_fsize);
  1709.       fprintf (file, "\tadd %%sp,64,%%g4\n\tadd %%sp,%%g1,%%sp\n");
  1710.     }
  1711.  
  1712.   /* If doing anything with PIC, do it now.  */
  1713.   if (! flag_pic)
  1714.     fprintf (file, "\t!#PROLOGUE# 1\n");
  1715.  
  1716.   /* Figure out where to save any special registers.  */
  1717.   if (num_fregs)
  1718.     {
  1719.       int offset, n_fregs = num_fregs;
  1720.  
  1721.       if (! leaf_function)
  1722.     offset = -apparent_fsize;
  1723.       else
  1724.     offset = 0;
  1725.  
  1726.       if (TARGET_EPILOGUE && ! leaf_function)
  1727.     n_fregs = save_regs (file, 0, 16, frame_base_name, offset, 0);
  1728.       else if (leaf_function)
  1729.     n_fregs = save_regs (file, 0, 32, frame_base_name, offset, 0);
  1730.       if (TARGET_EPILOGUE)
  1731.     save_regs (file, 32, FIRST_PSEUDO_REGISTER,
  1732.            frame_base_name, offset, n_fregs);
  1733.     }
  1734.  
  1735.   if (regs_ever_live[62])
  1736.     fprintf (file, "\tst %s,[%s-16]\n\tst %s,[%s-12]\n",
  1737.          reg_names[0], frame_base_name,
  1738.          reg_names[0], frame_base_name);
  1739.  
  1740.   leaf_label = 0;
  1741.   if (leaf_function && actual_fsize != 0)
  1742.     {
  1743.       /* warning ("leaf procedure with frame size %d", actual_fsize); */
  1744.       if (! TARGET_EPILOGUE)
  1745.     leaf_label = gen_label_rtx ();
  1746.     }
  1747. }
  1748.  
  1749. void
  1750. output_function_epilogue (file, size, leaf_function, true_epilogue)
  1751.      FILE *file;
  1752.      int size;
  1753. {
  1754.   extern char call_used_regs[];
  1755.   extern char *frame_base_name;
  1756.   int n_fregs, i;
  1757.  
  1758.   if (leaf_label)
  1759.     {
  1760.       if (leaf_function < 0)
  1761.     abort ();
  1762.       emit_label_after (leaf_label, get_last_insn ());
  1763.       final_scan_insn (get_last_insn (), file, 0, 0, 0, 1);
  1764.     }
  1765.  
  1766.   if (num_fregs)
  1767.     {
  1768.       int offset, n_fregs = num_fregs;
  1769.  
  1770.       if (! leaf_function)
  1771.     offset = -apparent_fsize;
  1772.       else
  1773.     offset = 0;
  1774.  
  1775.       if (TARGET_EPILOGUE && ! leaf_function)
  1776.     n_fregs = restore_regs (file, 0, 16, frame_base_name, offset, 0);
  1777.       else if (leaf_function)
  1778.     n_fregs = restore_regs (file, 0, 32, frame_base_name, offset, 0);
  1779.       if (TARGET_EPILOGUE)
  1780.     restore_regs (file, 32, FIRST_PSEUDO_REGISTER,
  1781.               frame_base_name, offset, n_fregs);
  1782.     }
  1783.  
  1784.   /* Tail calls have to do this work themselves.  */
  1785.   if (leaf_function >= 0)
  1786.     {
  1787.       if (TARGET_EPILOGUE || leaf_label)
  1788.     {
  1789.       int old_target_epilogue = TARGET_EPILOGUE;
  1790.       target_flags &= ~old_target_epilogue;
  1791.  
  1792.       if (! leaf_function)
  1793.         {
  1794.           /* If we wound up with things in our delay slot,
  1795.          flush them here.  */
  1796.           if (current_function_epilogue_delay_list)
  1797.         {
  1798.           rtx insn = emit_jump_insn_after (gen_rtx (RETURN, VOIDmode),
  1799.                            get_last_insn ());
  1800.           PATTERN (insn) = gen_rtx (PARALLEL, VOIDmode,
  1801.                         gen_rtvec (2,
  1802.                                PATTERN (XEXP (current_function_epilogue_delay_list, 0)),
  1803.                                PATTERN (insn)));
  1804.           final_scan_insn (insn, file, write_symbols, 1, 0, 1);
  1805.         }
  1806.           else
  1807.         fprintf (file, "\tret\n\trestore\n");
  1808.         }
  1809.       else if (actual_fsize < 4096)
  1810.         {
  1811.           if (current_function_epilogue_delay_list)
  1812.         {
  1813.           fprintf (file, "\tretl\n");
  1814.           final_scan_insn (XEXP (current_function_epilogue_delay_list, 0),
  1815.                    file, write_symbols, 1, 0, 1);
  1816.         }
  1817.           else
  1818.         fprintf (file, "\tretl\n\tadd %%sp,%d,%%sp\n", actual_fsize);
  1819.         }
  1820.       else
  1821.         {
  1822.           if (current_function_epilogue_delay_list)
  1823.         abort ();
  1824.           fprintf (file, "\tsethi %%hi(%d),%%g1\n\tor %%g1,%%lo(%d),%%g1\n\tretl\n\tadd %%sp,%%g1,%%sp\n",
  1825.                actual_fsize, actual_fsize);
  1826.         }
  1827.       target_flags |= old_target_epilogue;
  1828.     }
  1829.     }
  1830.   else if (true_epilogue)
  1831.     {
  1832.       warning ("tail call");
  1833.  
  1834.       /* We may still need a return insn!  Somebody could jump around
  1835.      the tail-calls that this function makes.  */
  1836.       if (TARGET_EPILOGUE)
  1837.     {
  1838.       rtx last = get_last_insn ();
  1839.  
  1840.       last = prev_nonnote_insn (last);
  1841.       if (last == 0
  1842.           || (GET_CODE (last) != JUMP_INSN && GET_CODE (last) != BARRIER))
  1843.         fprintf (file, "\tretl\n\tnop\n");
  1844.     }
  1845.     }
  1846. }
  1847.  
  1848. /* Return the string to output a conditional branch to LABEL, which is
  1849.    the operand number of the label.  OP is the conditional expression.  The
  1850.    mode of register 0 says what kind of comparison we made.
  1851.  
  1852.    REVERSED is non-zero if we should reverse the sense of the comparison.
  1853.  
  1854.    ANNUL is non-zero if we should generate an annulling branch.
  1855.  
  1856.    NOOP is non-zero if we have to follow this branch by a noop.  */
  1857.  
  1858. char *
  1859. output_cbranch (op, label, reversed, annul, noop)
  1860.      rtx op;
  1861.      int label;
  1862.      int reversed, annul, noop;
  1863. {
  1864.   static char string[20];
  1865.   enum rtx_code code = GET_CODE (op);
  1866.   enum machine_mode mode = GET_MODE (XEXP (op, 0));
  1867.   static char labelno[] = " %lX";
  1868.  
  1869.   /* If not floating-point or if EQ or NE, we can just reverse the code.  */
  1870.   if (reversed && (mode != CCFPmode || code == EQ || code == NE))
  1871.     code = reverse_condition (code), reversed = 0;
  1872.  
  1873.   /* Start by writing the branch condition.  */
  1874.   switch (code)
  1875.     {
  1876.     case NE:
  1877.       if (mode == CCFPmode)
  1878.     strcpy (string, "fbne");
  1879.       else
  1880.     strcpy (string, "bne");
  1881.       break;
  1882.  
  1883.     case EQ:
  1884.       if (mode == CCFPmode)
  1885.     strcpy (string, "fbe");
  1886.       else
  1887.     strcpy (string, "be");
  1888.       break;
  1889.  
  1890.     case GE:
  1891.       if (mode == CCFPmode)
  1892.     {
  1893.       if (reversed)
  1894.         strcpy (string, "fbul");
  1895.       else
  1896.         strcpy (string, "fbge");
  1897.     }
  1898.       else if (mode == CC_NOOVmode)
  1899.     strcpy (string, "bpos");
  1900.       else
  1901.     strcpy (string, "bge");
  1902.       break;
  1903.  
  1904.     case GT:
  1905.       if (mode == CCFPmode)
  1906.     {
  1907.       if (reversed)
  1908.         strcpy (string, "fbule");
  1909.       else
  1910.         strcpy (string, "fbg");
  1911.     }
  1912.       else
  1913.     strcpy (string, "bg");
  1914.       break;
  1915.  
  1916.     case LE:
  1917.       if (mode == CCFPmode)
  1918.     {
  1919.       if (reversed)
  1920.         strcpy (string, "fbug");
  1921.       else
  1922.         strcpy (string, "fble");
  1923.     }
  1924.       else
  1925.     strcpy (string, "ble");
  1926.       break;
  1927.  
  1928.     case LT:
  1929.       if (mode == CCFPmode)
  1930.     {
  1931.       if (reversed)
  1932.         strcpy (string, "fbuge");
  1933.       else
  1934.         strcpy (string, "fbl");
  1935.     }
  1936.       else if (mode == CC_NOOVmode)
  1937.     strcpy (string, "bneg");
  1938.       else
  1939.     strcpy (string, "bl");
  1940.       break;
  1941.  
  1942.     case GEU:
  1943.       strcpy (string, "bgeu");
  1944.       break;
  1945.  
  1946.     case GTU:
  1947.       strcpy (string, "bgu");
  1948.       break;
  1949.  
  1950.     case LEU:
  1951.       strcpy (string, "bleu");
  1952.       break;
  1953.  
  1954.     case LTU:
  1955.       strcpy (string, "blu");
  1956.       break;
  1957.     }
  1958.  
  1959.   /* Now add the annulling, the label, and a possible noop.  */
  1960.   if (annul)
  1961.     strcat (string, ",a");
  1962.  
  1963.   labelno[3] = label + '0';
  1964.   strcat (string, labelno);
  1965.  
  1966.   if (noop)
  1967.     strcat (string, "\n\tnop");
  1968.  
  1969.   return string;
  1970. }
  1971.  
  1972. char *
  1973. output_return (operands)
  1974.      rtx *operands;
  1975. {
  1976.   if (leaf_label)
  1977.     {
  1978.       operands[0] = leaf_label;
  1979.       return "b,a %l0";
  1980.     }
  1981.   else if (leaf_function)
  1982.     {
  1983.       operands[0] = gen_rtx (CONST_INT, VOIDmode, actual_fsize);
  1984.       if (actual_fsize < 4096)
  1985.     return "retl\n\tadd %%sp,%0,%%sp";
  1986.       else
  1987.     return "sethi %%hi(%a0),%%g1\n\tor %%g1,%%lo(%a0),%%g1\n\tretl\n\tadd %%sp,%%g1,%%sp";
  1988.     }
  1989.   else
  1990.     return "ret\n\trestore";
  1991. }
  1992.  
  1993. char *
  1994. output_floatsisf2 (operands)
  1995.      rtx *operands;
  1996. {
  1997.   if (GET_CODE (operands[1]) == MEM)
  1998.     return "ld %1,%0\n\tfitos %0,%0";
  1999.   else if (FP_REG_P (operands[1]))
  2000.     return "fitos %1,%0";
  2001.   return "st %r1,[%%fp-4]\n\tld [%%fp-4],%0\n\tfitos %0,%0";
  2002. }
  2003.  
  2004. char *
  2005. output_floatsidf2 (operands)
  2006.      rtx *operands;
  2007. {
  2008.   if (GET_CODE (operands[1]) == MEM)
  2009.     return "ld %1,%0\n\tfitod %0,%0";
  2010.   else if (FP_REG_P (operands[1]))
  2011.     return "fitod %1,%0";
  2012.   return "st %r1,[%%fp-4]\n\tld [%%fp-4],%0\n\tfitod %0,%0";
  2013. }
  2014.  
  2015. int
  2016. tail_call_valid_p ()
  2017. {
  2018.   static int checked = 0;
  2019.   static int valid_p = 0;
  2020.  
  2021.   if (! checked)
  2022.     {
  2023.       register int i;
  2024.  
  2025.       checked = 1;
  2026.       for (i = 32; i < FIRST_PSEUDO_REGISTER; i++)
  2027.     if (! fixed_regs[i] && ! call_used_regs[i])
  2028.       return 0;
  2029.       valid_p = 1;
  2030.     }
  2031.   return valid_p;
  2032. }
  2033.  
  2034. /* Leaf functions and non-leaf functions have different needs.  */
  2035.  
  2036. static int
  2037. reg_leaf_alloc_order[] = REG_LEAF_ALLOC_ORDER;
  2038.  
  2039. static int
  2040. reg_nonleaf_alloc_order[] = REG_ALLOC_ORDER;
  2041.  
  2042. static int *reg_alloc_orders[] = {
  2043.   reg_leaf_alloc_order,
  2044.   reg_nonleaf_alloc_order};
  2045.  
  2046. void
  2047. order_regs_for_local_alloc ()
  2048. {
  2049.   static int last_order_nonleaf = 1;
  2050.  
  2051.   if (regs_ever_live[15] != last_order_nonleaf)
  2052.     {
  2053.       last_order_nonleaf = !last_order_nonleaf;
  2054.       bcopy (reg_alloc_orders[last_order_nonleaf], reg_alloc_order,
  2055.          FIRST_PSEUDO_REGISTER * sizeof (int));
  2056.     }
  2057. }
  2058.  
  2059. /* Machine dependent routines for the branch probability, arc profiling
  2060.    code.  */
  2061.  
  2062. /* The label used by the arc profiling code.  */
  2063.  
  2064. static rtx profiler_label;
  2065.  
  2066. void
  2067. init_arc_profiler ()
  2068. {
  2069.   /* Generate and save a copy of this so it can be shared.  */
  2070.   profiler_label = gen_rtx (SYMBOL_REF, SImode, "*LPBX2");
  2071. }
  2072.  
  2073. void
  2074. output_arc_profiler (arcno, insert_after)
  2075.      int arcno;
  2076.      rtx insert_after;
  2077. {
  2078.   rtx profiler_target_addr
  2079.     = gen_rtx (CONST, SImode,
  2080.            gen_rtx (PLUS, SImode, profiler_label,
  2081.             gen_rtx (CONST_INT, VOIDmode, 4 * arcno)));
  2082.   register rtx profiler_reg = gen_reg_rtx (SImode);
  2083.   register rtx temp = gen_reg_rtx (Pmode);
  2084.   register rtx profiler_target = gen_rtx (MEM, SImode,
  2085.                       gen_rtx (LO_SUM, Pmode, temp,
  2086.                            profiler_target_addr));
  2087.   /* The insns are emitted from last to first after the insn insert_after.
  2088.      Emit_insn_after is used because sometimes we want to put the
  2089.      instrumentation code after the last insn of the function.  */
  2090.   emit_insn_after (gen_rtx (SET, VOIDmode, profiler_target, profiler_reg),
  2091.            insert_after);
  2092.   emit_insn_after (gen_rtx (SET, VOIDmode, profiler_reg,
  2093.                 gen_rtx (PLUS, SImode, profiler_reg, const1_rtx)),
  2094.            insert_after);
  2095.   emit_insn_after (gen_rtx (SET, VOIDmode, profiler_reg, profiler_target),
  2096.            insert_after);
  2097.   emit_insn_after (gen_rtx (SET, VOIDmode, temp,
  2098.                 gen_rtx (HIGH, Pmode, profiler_target_addr)),
  2099.            insert_after);
  2100. }
  2101.  
  2102. /* All the remaining routines in this file have been turned off.  */
  2103. #if 0
  2104. static char *
  2105. output_pic_sequence (temp, from, template, operands)
  2106.      int temp;
  2107.      int from;
  2108.      char *template;
  2109.      rtx *operands;
  2110. {
  2111.   char buf[80];
  2112.   rtx *xoperands = (rtx *)alloca ((temp+3)*sizeof (rtx));
  2113.   rtx addr = operands[from];
  2114.  
  2115.   bcopy (operands, xoperands, temp*sizeof (rtx));
  2116.   xoperands[temp] = pic_offset_table_rtx;
  2117.  
  2118.   if (GET_CODE (addr) == MEM)
  2119.     addr = XEXP (addr, 0);
  2120.   if (GET_CODE (addr) == SYMBOL_REF)
  2121.     {
  2122.       xoperands[temp+1] = addr;
  2123.       xoperands[temp+2] = const0_rtx;
  2124.     }
  2125.   else if (GET_CODE (addr) == CONST)
  2126.     {
  2127.       if (GET_CODE (XEXP (addr, 0)) == PLUS)
  2128.     {
  2129.       xoperands[temp+1] = addr = XEXP (XEXP (addr, 0), 0);
  2130.       xoperands[temp+2] = XEXP (XEXP (addr, 0), 1);
  2131.     }
  2132.       else abort ();
  2133.       if (GET_CODE (addr) != SYMBOL_REF
  2134.       || GET_CODE (xoperands[temp+2]) != CONST_INT)
  2135.     abort ();
  2136.       if (! SMALL_INT (xoperands[temp+2]))
  2137.     {
  2138.       output_asm_insn ("sethi %%hi(%a0),%%g2\n\tor %%g2,%%lo(%a0),%%g2", xoperands+temp+2);
  2139.       xoperands[temp+2] = gen_rtx (REG, SImode, 2);
  2140.     }
  2141.     }
  2142.   else abort ();
  2143.  
  2144.   if ((cc_prev_status.flags & CC_KNOW_HI_G1)
  2145.       && rtx_equal_p (cc_prev_status.mdep, addr))
  2146.     return "";
  2147.   cc_status.flags |= CC_KNOW_HI_G1;
  2148.   cc_status.mdep = addr;
  2149.   abort ();
  2150.   sprintf (buf, "ld [%%d+%%d],%%%%g1", temp, from);
  2151.   output_asm_insn (buf, xoperands);
  2152.   output_asm_insn (template, xoperands);
  2153.   return "";
  2154. }
  2155.  
  2156. static char *
  2157. output_pic_sequence_2 (temp, from, template, operands, need_nop_at_end)
  2158.      int temp;
  2159.      int from;
  2160.      char *template;
  2161.      rtx *operands;
  2162. {
  2163.   output_pic_sequence (temp, from, template, operands);
  2164.   if (need_nop_at_end)
  2165.     return "nop";
  2166.   return "";
  2167. }
  2168.  
  2169. void
  2170. fp_zero_hook (insn, operands, noperands)
  2171.      rtx insn;
  2172.      rtx *operands;
  2173.      int noperands;
  2174. {
  2175.   int i;
  2176.   for (i = 0; i < noperands; i++)
  2177.     if (GET_CODE (operands[i]) == CONST_DOUBLE)
  2178.       {
  2179.     if (TARGET_GNU)
  2180.       ;
  2181.     else if (GET_MODE (operands[0]) == SFmode)
  2182.       output_asm_insn ("ld [%@-16],%%f30", 0);
  2183.     else if (GET_MODE (operands[0]) == DFmode)
  2184.       {
  2185.         output_asm_insn ("ld [%@-16],%%f30", 0);
  2186.         output_asm_insn ("ld [%@-12],%%f31", 0);
  2187.       }
  2188.     else abort ();
  2189.     break;
  2190.       }
  2191. }
  2192.  
  2193. char *
  2194. output_tail_call (operands, insn)
  2195.      rtx *operands;
  2196.      rtx insn;
  2197. {
  2198.   extern FILE *asm_out_file;
  2199.   int this_fsize = actual_fsize;
  2200.   rtx next;
  2201.   int need_nop_at_end = 0;
  2202.  
  2203.   next = next_real_insn (insn);
  2204.   while (next && GET_CODE (next) == CODE_LABEL)
  2205.     next = next_real_insn (insn);
  2206.  
  2207.   if (final_sequence && this_fsize > 0)
  2208.     {
  2209.       rtx xoperands[1];
  2210.  
  2211.       /* If we have to restore any registers, don't take any chances
  2212.      restoring a register before we discharge it into
  2213.      its home.  If the frame size is only 88, we are guaranteed
  2214.      that the epilogue will fit in the delay slot.  */
  2215.       rtx delay_insn = XVECEXP (final_sequence, 0, 1);
  2216.       if (GET_CODE (PATTERN (delay_insn)) == SET)
  2217.     {
  2218.       rtx dest = SET_DEST (PATTERN (delay_insn));
  2219.       if (GET_CODE (dest) == REG
  2220.           && reg_mentioned_p (dest, insn))
  2221.         abort ();
  2222.     }
  2223.       else if (GET_CODE (PATTERN (delay_insn)) == PARALLEL)
  2224.     abort ();
  2225.       xoperands[0] = operands[0];
  2226.       final_scan_insn (delay_insn, asm_out_file, write_symbols, 0, 0, 1);
  2227.       operands[0] = xoperands[0];
  2228.       final_sequence = 0;
  2229.     }
  2230.  
  2231.   /* Make sure we are clear to return.  */
  2232.   output_function_epilogue (asm_out_file, get_frame_size (), -1, 0);
  2233.  
  2234.   /* Strip the MEM.  */
  2235.   operands[0] = XEXP (operands[0], 0);
  2236.  
  2237.   if (final_sequence == 0
  2238.       && (next == 0
  2239.       || GET_CODE (next) == CALL_INSN
  2240.       || GET_CODE (next) == JUMP_INSN))
  2241.     need_nop_at_end = 1;
  2242.  
  2243.   if (flag_pic)
  2244.     return output_pic_sequence_2 (2, 3, 0, "jmpl %%g1+%3", operands, need_nop_at_end);
  2245.  
  2246.   if (GET_CODE (operands[0]) == REG)
  2247.     output_asm_insn ("jmpl %a0,%%g0", operands);
  2248.   else if (TARGET_TAIL_CALL)
  2249.     {
  2250.       /* We assume all labels will be within 16 MB of our call.  */
  2251.       if (need_nop_at_end || final_sequence)
  2252.     output_asm_insn ("b %a0", operands);
  2253.       else
  2254.     output_asm_insn ("b,a %a0", operands);
  2255.     }
  2256.   else if (! final_sequence)
  2257.     {
  2258.       output_asm_insn ("sethi %%hi(%a0),%%g1\n\tjmpl %%g1+%%lo(%a0),%%g1",
  2259.                operands);
  2260.     }
  2261.   else
  2262.     {
  2263.       int i;
  2264.       rtx x = PATTERN (XVECEXP (final_sequence, 0, 1));
  2265.       for (i = 1; i < 32; i++)
  2266.     if ((i == 1 || ! fixed_regs[i])
  2267.         && call_used_regs[i]
  2268.         && ! refers_to_regno_p (i, i+1, x, 0))
  2269.       break;
  2270.       if (i == 32)
  2271.     abort ();
  2272.       operands[1] = gen_rtx (REG, SImode, i);
  2273.       output_asm_insn ("sethi %%hi(%a0),%1\n\tjmpl %1+%%lo(%a0),%1", operands);
  2274.     }
  2275.   return (need_nop_at_end ? "nop" : "");
  2276. }
  2277. #endif
  2278.