118334Speter/* Subroutines for manipulating rtx's in semantically interesting ways.
290075Sobrien   Copyright (C) 1987, 1991, 1994, 1995, 1996, 1997, 1998,
3169689Skan   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
4169689Skan   Free Software Foundation, Inc.
518334Speter
690075SobrienThis file is part of GCC.
718334Speter
890075SobrienGCC is free software; you can redistribute it and/or modify it under
990075Sobrienthe terms of the GNU General Public License as published by the Free
1090075SobrienSoftware Foundation; either version 2, or (at your option) any later
1190075Sobrienversion.
1218334Speter
1390075SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY
1490075SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or
1590075SobrienFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1690075Sobrienfor more details.
1718334Speter
1818334SpeterYou should have received a copy of the GNU General Public License
1990075Sobrienalong with GCC; see the file COPYING.  If not, write to the Free
20169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
21169689Skan02110-1301, USA.  */
2218334Speter
2318334Speter
2418334Speter#include "config.h"
2550397Sobrien#include "system.h"
26132718Skan#include "coretypes.h"
27132718Skan#include "tm.h"
2852284Sobrien#include "toplev.h"
2918334Speter#include "rtl.h"
3018334Speter#include "tree.h"
3190075Sobrien#include "tm_p.h"
3218334Speter#include "flags.h"
3390075Sobrien#include "function.h"
3418334Speter#include "expr.h"
3590075Sobrien#include "optabs.h"
3618334Speter#include "hard-reg-set.h"
3718334Speter#include "insn-config.h"
3890075Sobrien#include "ggc.h"
3918334Speter#include "recog.h"
40102780Skan#include "langhooks.h"
41169689Skan#include "target.h"
42169689Skan#include "output.h"
4318334Speter
44132718Skanstatic rtx break_out_memory_refs (rtx);
45132718Skanstatic void emit_stack_probe (rtx);
4652284Sobrien
4790075Sobrien
4890075Sobrien/* Truncate and perhaps sign-extend C as appropriate for MODE.  */
4990075Sobrien
5090075SobrienHOST_WIDE_INT
51132718Skantrunc_int_for_mode (HOST_WIDE_INT c, enum machine_mode mode)
5290075Sobrien{
5390075Sobrien  int width = GET_MODE_BITSIZE (mode);
5490075Sobrien
55117395Skan  /* You want to truncate to a _what_?  */
56169689Skan  gcc_assert (SCALAR_INT_MODE_P (mode));
57117395Skan
5890075Sobrien  /* Canonicalize BImode to 0 and STORE_FLAG_VALUE.  */
5990075Sobrien  if (mode == BImode)
6090075Sobrien    return c & 1 ? STORE_FLAG_VALUE : 0;
6190075Sobrien
6290075Sobrien  /* Sign-extend for the requested mode.  */
6390075Sobrien
6490075Sobrien  if (width < HOST_BITS_PER_WIDE_INT)
6590075Sobrien    {
6690075Sobrien      HOST_WIDE_INT sign = 1;
6790075Sobrien      sign <<= width - 1;
6890075Sobrien      c &= (sign << 1) - 1;
6990075Sobrien      c ^= sign;
7090075Sobrien      c -= sign;
7190075Sobrien    }
7290075Sobrien
7390075Sobrien  return c;
7490075Sobrien}
7590075Sobrien
76169689Skan/* Return an rtx for the sum of X and the integer C.  */
7718334Speter
7818334Speterrtx
79169689Skanplus_constant (rtx x, HOST_WIDE_INT c)
8018334Speter{
8190075Sobrien  RTX_CODE code;
8290075Sobrien  rtx y;
8390075Sobrien  enum machine_mode mode;
8490075Sobrien  rtx tem;
8518334Speter  int all_constant = 0;
8618334Speter
8718334Speter  if (c == 0)
8818334Speter    return x;
8918334Speter
9018334Speter restart:
9118334Speter
9218334Speter  code = GET_CODE (x);
9318334Speter  mode = GET_MODE (x);
9490075Sobrien  y = x;
9590075Sobrien
9618334Speter  switch (code)
9718334Speter    {
9818334Speter    case CONST_INT:
9918334Speter      return GEN_INT (INTVAL (x) + c);
10018334Speter
10118334Speter    case CONST_DOUBLE:
10218334Speter      {
10390075Sobrien	unsigned HOST_WIDE_INT l1 = CONST_DOUBLE_LOW (x);
10418334Speter	HOST_WIDE_INT h1 = CONST_DOUBLE_HIGH (x);
10590075Sobrien	unsigned HOST_WIDE_INT l2 = c;
10618334Speter	HOST_WIDE_INT h2 = c < 0 ? ~0 : 0;
10790075Sobrien	unsigned HOST_WIDE_INT lv;
10890075Sobrien	HOST_WIDE_INT hv;
10918334Speter
11018334Speter	add_double (l1, h1, l2, h2, &lv, &hv);
11118334Speter
11218334Speter	return immed_double_const (lv, hv, VOIDmode);
11318334Speter      }
11418334Speter
11518334Speter    case MEM:
11618334Speter      /* If this is a reference to the constant pool, try replacing it with
11718334Speter	 a reference to a new constant.  If the resulting address isn't
11818334Speter	 valid, don't return it because we have no way to validize it.  */
11918334Speter      if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
12018334Speter	  && CONSTANT_POOL_ADDRESS_P (XEXP (x, 0)))
12118334Speter	{
12218334Speter	  tem
12318334Speter	    = force_const_mem (GET_MODE (x),
12418334Speter			       plus_constant (get_pool_constant (XEXP (x, 0)),
12518334Speter					      c));
12618334Speter	  if (memory_address_p (GET_MODE (tem), XEXP (tem, 0)))
12718334Speter	    return tem;
12818334Speter	}
12918334Speter      break;
13018334Speter
13118334Speter    case CONST:
13218334Speter      /* If adding to something entirely constant, set a flag
13318334Speter	 so that we can add a CONST around the result.  */
13418334Speter      x = XEXP (x, 0);
13518334Speter      all_constant = 1;
13618334Speter      goto restart;
13718334Speter
13818334Speter    case SYMBOL_REF:
13918334Speter    case LABEL_REF:
14018334Speter      all_constant = 1;
14118334Speter      break;
14218334Speter
14318334Speter    case PLUS:
14418334Speter      /* The interesting case is adding the integer to a sum.
14518334Speter	 Look for constant term in the sum and combine
14618334Speter	 with C.  For an integer constant term, we make a combined
14718334Speter	 integer.  For a constant term that is not an explicit integer,
14896263Sobrien	 we cannot really combine, but group them together anyway.
14918334Speter
15052284Sobrien	 Restart or use a recursive call in case the remaining operand is
15152284Sobrien	 something that we handle specially, such as a SYMBOL_REF.
15218334Speter
15352284Sobrien	 We may not immediately return from the recursive call here, lest
15452284Sobrien	 all_constant gets lost.  */
15552284Sobrien
15618334Speter      if (GET_CODE (XEXP (x, 1)) == CONST_INT)
15752284Sobrien	{
15852284Sobrien	  c += INTVAL (XEXP (x, 1));
15990075Sobrien
16090075Sobrien	  if (GET_MODE (x) != VOIDmode)
16190075Sobrien	    c = trunc_int_for_mode (c, GET_MODE (x));
16290075Sobrien
16352284Sobrien	  x = XEXP (x, 0);
16452284Sobrien	  goto restart;
16552284Sobrien	}
16690075Sobrien      else if (CONSTANT_P (XEXP (x, 1)))
16752284Sobrien	{
16890075Sobrien	  x = gen_rtx_PLUS (mode, XEXP (x, 0), plus_constant (XEXP (x, 1), c));
16952284Sobrien	  c = 0;
17052284Sobrien	}
17190075Sobrien      else if (find_constant_term_loc (&y))
17252284Sobrien	{
17390075Sobrien	  /* We need to be careful since X may be shared and we can't
17490075Sobrien	     modify it in place.  */
17590075Sobrien	  rtx copy = copy_rtx (x);
17690075Sobrien	  rtx *const_loc = find_constant_term_loc (&copy);
17790075Sobrien
17890075Sobrien	  *const_loc = plus_constant (*const_loc, c);
17990075Sobrien	  x = copy;
18052284Sobrien	  c = 0;
18152284Sobrien	}
18250397Sobrien      break;
18390075Sobrien
18450397Sobrien    default:
18550397Sobrien      break;
18618334Speter    }
18718334Speter
18818334Speter  if (c != 0)
18950397Sobrien    x = gen_rtx_PLUS (mode, x, GEN_INT (c));
19018334Speter
19118334Speter  if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF)
19218334Speter    return x;
19318334Speter  else if (all_constant)
19450397Sobrien    return gen_rtx_CONST (mode, x);
19518334Speter  else
19618334Speter    return x;
19718334Speter}
19818334Speter
19918334Speter/* If X is a sum, return a new sum like X but lacking any constant terms.
20018334Speter   Add all the removed constant terms into *CONSTPTR.
20118334Speter   X itself is not altered.  The result != X if and only if
20218334Speter   it is not isomorphic to X.  */
20318334Speter
20418334Speterrtx
205132718Skaneliminate_constant_term (rtx x, rtx *constptr)
20618334Speter{
20790075Sobrien  rtx x0, x1;
20818334Speter  rtx tem;
20918334Speter
21018334Speter  if (GET_CODE (x) != PLUS)
21118334Speter    return x;
21218334Speter
21318334Speter  /* First handle constants appearing at this level explicitly.  */
21418334Speter  if (GET_CODE (XEXP (x, 1)) == CONST_INT
21518334Speter      && 0 != (tem = simplify_binary_operation (PLUS, GET_MODE (x), *constptr,
21618334Speter						XEXP (x, 1)))
21718334Speter      && GET_CODE (tem) == CONST_INT)
21818334Speter    {
21918334Speter      *constptr = tem;
22018334Speter      return eliminate_constant_term (XEXP (x, 0), constptr);
22118334Speter    }
22218334Speter
22318334Speter  tem = const0_rtx;
22418334Speter  x0 = eliminate_constant_term (XEXP (x, 0), &tem);
22518334Speter  x1 = eliminate_constant_term (XEXP (x, 1), &tem);
22618334Speter  if ((x1 != XEXP (x, 1) || x0 != XEXP (x, 0))
22718334Speter      && 0 != (tem = simplify_binary_operation (PLUS, GET_MODE (x),
22818334Speter						*constptr, tem))
22918334Speter      && GET_CODE (tem) == CONST_INT)
23018334Speter    {
23118334Speter      *constptr = tem;
23250397Sobrien      return gen_rtx_PLUS (GET_MODE (x), x0, x1);
23318334Speter    }
23418334Speter
23518334Speter  return x;
23618334Speter}
23718334Speter
23818334Speter/* Return an rtx for the size in bytes of the value of EXP.  */
23918334Speter
24018334Speterrtx
241132718Skanexpr_size (tree exp)
24218334Speter{
243169689Skan  tree size;
24418334Speter
245169689Skan  if (TREE_CODE (exp) == WITH_SIZE_EXPR)
246169689Skan    size = TREE_OPERAND (exp, 1);
247169689Skan  else
248169689Skan    size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (lang_hooks.expr_size (exp), exp);
24918334Speter
25090075Sobrien  return expand_expr (size, NULL_RTX, TYPE_MODE (sizetype), 0);
251102780Skan}
25290075Sobrien
253102780Skan/* Return a wide integer for the size in bytes of the value of EXP, or -1
254102780Skan   if the size can vary or is larger than an integer.  */
255102780Skan
256102780SkanHOST_WIDE_INT
257132718Skanint_expr_size (tree exp)
258102780Skan{
259169689Skan  tree size;
260102780Skan
261169689Skan  if (TREE_CODE (exp) == WITH_SIZE_EXPR)
262169689Skan    size = TREE_OPERAND (exp, 1);
263169689Skan  else
264169689Skan    size = lang_hooks.expr_size (exp);
265169689Skan
266169689Skan  if (size == 0 || !host_integerp (size, 0))
267102780Skan    return -1;
268102780Skan
269169689Skan  return tree_low_cst (size, 0);
27018334Speter}
27118334Speter
27218334Speter/* Return a copy of X in which all memory references
27318334Speter   and all constants that involve symbol refs
27418334Speter   have been replaced with new temporary registers.
27518334Speter   Also emit code to load the memory locations and constants
27618334Speter   into those registers.
27718334Speter
27818334Speter   If X contains no such constants or memory references,
27918334Speter   X itself (not a copy) is returned.
28018334Speter
28118334Speter   If a constant is found in the address that is not a legitimate constant
28218334Speter   in an insn, it is left alone in the hope that it might be valid in the
28318334Speter   address.
28418334Speter
28518334Speter   X may contain no arithmetic except addition, subtraction and multiplication.
28618334Speter   Values returned by expand_expr with 1 for sum_ok fit this constraint.  */
28718334Speter
28818334Speterstatic rtx
289132718Skanbreak_out_memory_refs (rtx x)
29018334Speter{
291169689Skan  if (MEM_P (x)
29218334Speter      || (CONSTANT_P (x) && CONSTANT_ADDRESS_P (x)
29318334Speter	  && GET_MODE (x) != VOIDmode))
29418334Speter    x = force_reg (GET_MODE (x), x);
29518334Speter  else if (GET_CODE (x) == PLUS || GET_CODE (x) == MINUS
29618334Speter	   || GET_CODE (x) == MULT)
29718334Speter    {
29890075Sobrien      rtx op0 = break_out_memory_refs (XEXP (x, 0));
29990075Sobrien      rtx op1 = break_out_memory_refs (XEXP (x, 1));
30018334Speter
30118334Speter      if (op0 != XEXP (x, 0) || op1 != XEXP (x, 1))
30250397Sobrien	x = gen_rtx_fmt_ee (GET_CODE (x), Pmode, op0, op1);
30318334Speter    }
30418334Speter
30518334Speter  return x;
30618334Speter}
30718334Speter
30818334Speter/* Given X, a memory address in ptr_mode, convert it to an address
30918334Speter   in Pmode, or vice versa (TO_MODE says which way).  We take advantage of
31018334Speter   the fact that pointers are not allowed to overflow by commuting arithmetic
31118334Speter   operations over conversions so that address arithmetic insns can be
31218334Speter   used.  */
31318334Speter
31418334Speterrtx
315132718Skanconvert_memory_address (enum machine_mode to_mode ATTRIBUTE_UNUSED,
316132718Skan			rtx x)
31718334Speter{
318132718Skan#ifndef POINTERS_EXTEND_UNSIGNED
319169689Skan  gcc_assert (GET_MODE (x) == to_mode || GET_MODE (x) == VOIDmode);
320132718Skan  return x;
321132718Skan#else /* defined(POINTERS_EXTEND_UNSIGNED) */
322132718Skan  enum machine_mode from_mode;
32318334Speter  rtx temp;
324117395Skan  enum rtx_code code;
32518334Speter
326132718Skan  /* If X already has the right mode, just return it.  */
327132718Skan  if (GET_MODE (x) == to_mode)
328132718Skan    return x;
329132718Skan
330132718Skan  from_mode = to_mode == ptr_mode ? Pmode : ptr_mode;
331132718Skan
33250397Sobrien  /* Here we handle some special cases.  If none of them apply, fall through
33350397Sobrien     to the default case.  */
33418334Speter  switch (GET_CODE (x))
33518334Speter    {
33618334Speter    case CONST_INT:
33718334Speter    case CONST_DOUBLE:
338117395Skan      if (GET_MODE_SIZE (to_mode) < GET_MODE_SIZE (from_mode))
339117395Skan	code = TRUNCATE;
340117395Skan      else if (POINTERS_EXTEND_UNSIGNED < 0)
341117395Skan	break;
342117395Skan      else if (POINTERS_EXTEND_UNSIGNED > 0)
343117395Skan	code = ZERO_EXTEND;
344117395Skan      else
345117395Skan	code = SIGN_EXTEND;
346117395Skan      temp = simplify_unary_operation (code, to_mode, x, from_mode);
347117395Skan      if (temp)
348117395Skan	return temp;
349117395Skan      break;
35018334Speter
35190075Sobrien    case SUBREG:
352117395Skan      if ((SUBREG_PROMOTED_VAR_P (x) || REG_POINTER (SUBREG_REG (x)))
35390075Sobrien	  && GET_MODE (SUBREG_REG (x)) == to_mode)
35490075Sobrien	return SUBREG_REG (x);
35590075Sobrien      break;
35690075Sobrien
35718334Speter    case LABEL_REF:
358117395Skan      temp = gen_rtx_LABEL_REF (to_mode, XEXP (x, 0));
359117395Skan      LABEL_REF_NONLOCAL_P (temp) = LABEL_REF_NONLOCAL_P (x);
360117395Skan      return temp;
36190075Sobrien      break;
36218334Speter
36318334Speter    case SYMBOL_REF:
364117395Skan      temp = shallow_copy_rtx (x);
365117395Skan      PUT_MODE (temp, to_mode);
366117395Skan      return temp;
36790075Sobrien      break;
36818334Speter
36950397Sobrien    case CONST:
370117395Skan      return gen_rtx_CONST (to_mode,
371117395Skan			    convert_memory_address (to_mode, XEXP (x, 0)));
37290075Sobrien      break;
37350397Sobrien
37418334Speter    case PLUS:
37518334Speter    case MULT:
376117395Skan      /* For addition we can safely permute the conversion and addition
377117395Skan	 operation if one operand is a constant and converting the constant
378117395Skan	 does not change it.  We can always safely permute them if we are
379117395Skan	 making the address narrower.  */
380117395Skan      if (GET_MODE_SIZE (to_mode) < GET_MODE_SIZE (from_mode)
381117395Skan	  || (GET_CODE (x) == PLUS
382117395Skan	      && GET_CODE (XEXP (x, 1)) == CONST_INT
383117395Skan	      && XEXP (x, 1) == convert_memory_address (to_mode, XEXP (x, 1))))
38496263Sobrien	return gen_rtx_fmt_ee (GET_CODE (x), to_mode,
38550397Sobrien			       convert_memory_address (to_mode, XEXP (x, 0)),
386117395Skan			       XEXP (x, 1));
38750397Sobrien      break;
38896263Sobrien
38918334Speter    default:
39050397Sobrien      break;
39118334Speter    }
39250397Sobrien
39350397Sobrien  return convert_modes (to_mode, from_mode,
39450397Sobrien			x, POINTERS_EXTEND_UNSIGNED);
395132718Skan#endif /* defined(POINTERS_EXTEND_UNSIGNED) */
39618334Speter}
39718334Speter
39818334Speter/* Return something equivalent to X but valid as a memory address
39918334Speter   for something of mode MODE.  When X is not itself valid, this
40018334Speter   works by copying X or subexpressions of it into registers.  */
40118334Speter
40218334Speterrtx
403132718Skanmemory_address (enum machine_mode mode, rtx x)
40418334Speter{
40590075Sobrien  rtx oldx = x;
40618334Speter
407132718Skan  x = convert_memory_address (Pmode, x);
40818334Speter
409132718Skan  /* By passing constant addresses through registers
41018334Speter     we get a chance to cse them.  */
41118334Speter  if (! cse_not_expected && CONSTANT_P (x) && CONSTANT_ADDRESS_P (x))
41218334Speter    x = force_reg (Pmode, x);
41318334Speter
41418334Speter  /* We get better cse by rejecting indirect addressing at this stage.
41518334Speter     Let the combiner create indirect addresses where appropriate.
41618334Speter     For now, generate the code so that the subexpressions useful to share
41718334Speter     are visible.  But not if cse won't be done!  */
41818334Speter  else
41918334Speter    {
420169689Skan      if (! cse_not_expected && !REG_P (x))
42118334Speter	x = break_out_memory_refs (x);
42218334Speter
42318334Speter      /* At this point, any valid address is accepted.  */
424169689Skan      if (memory_address_p (mode, x))
425169689Skan	goto win;
42618334Speter
42718334Speter      /* If it was valid before but breaking out memory refs invalidated it,
42818334Speter	 use it the old way.  */
42918334Speter      if (memory_address_p (mode, oldx))
43018334Speter	goto win2;
43118334Speter
43218334Speter      /* Perform machine-dependent transformations on X
43318334Speter	 in certain cases.  This is not necessary since the code
43418334Speter	 below can handle all possible cases, but machine-dependent
43518334Speter	 transformations can make better code.  */
43618334Speter      LEGITIMIZE_ADDRESS (x, oldx, mode, win);
43718334Speter
43818334Speter      /* PLUS and MULT can appear in special ways
43918334Speter	 as the result of attempts to make an address usable for indexing.
44018334Speter	 Usually they are dealt with by calling force_operand, below.
44118334Speter	 But a sum containing constant terms is special
44218334Speter	 if removing them makes the sum a valid address:
44318334Speter	 then we generate that address in a register
44418334Speter	 and index off of it.  We do this because it often makes
44518334Speter	 shorter code, and because the addresses thus generated
44618334Speter	 in registers often become common subexpressions.  */
44718334Speter      if (GET_CODE (x) == PLUS)
44818334Speter	{
44918334Speter	  rtx constant_term = const0_rtx;
45018334Speter	  rtx y = eliminate_constant_term (x, &constant_term);
45118334Speter	  if (constant_term == const0_rtx
45218334Speter	      || ! memory_address_p (mode, y))
45318334Speter	    x = force_operand (x, NULL_RTX);
45418334Speter	  else
45518334Speter	    {
45650397Sobrien	      y = gen_rtx_PLUS (GET_MODE (x), copy_to_reg (y), constant_term);
45718334Speter	      if (! memory_address_p (mode, y))
45818334Speter		x = force_operand (x, NULL_RTX);
45918334Speter	      else
46018334Speter		x = y;
46118334Speter	    }
46218334Speter	}
46318334Speter
46418334Speter      else if (GET_CODE (x) == MULT || GET_CODE (x) == MINUS)
46518334Speter	x = force_operand (x, NULL_RTX);
46618334Speter
46718334Speter      /* If we have a register that's an invalid address,
46818334Speter	 it must be a hard reg of the wrong class.  Copy it to a pseudo.  */
469169689Skan      else if (REG_P (x))
47018334Speter	x = copy_to_reg (x);
47118334Speter
47218334Speter      /* Last resort: copy the value to a register, since
47318334Speter	 the register is a valid address.  */
47418334Speter      else
47518334Speter	x = force_reg (Pmode, x);
47618334Speter
47718334Speter      goto done;
47818334Speter
47918334Speter    win2:
48018334Speter      x = oldx;
48118334Speter    win:
482169689Skan      if (flag_force_addr && ! cse_not_expected && !REG_P (x))
48318334Speter	{
484169689Skan	  x = force_operand (x, NULL_RTX);
485169689Skan	  x = force_reg (Pmode, x);
48618334Speter	}
48718334Speter    }
48818334Speter
48918334Speter done:
49018334Speter
49118334Speter  /* If we didn't change the address, we are done.  Otherwise, mark
49218334Speter     a reg as a pointer if we have REG or REG + CONST_INT.  */
49318334Speter  if (oldx == x)
49418334Speter    return x;
495169689Skan  else if (REG_P (x))
49690075Sobrien    mark_reg_pointer (x, BITS_PER_UNIT);
49718334Speter  else if (GET_CODE (x) == PLUS
498169689Skan	   && REG_P (XEXP (x, 0))
49918334Speter	   && GET_CODE (XEXP (x, 1)) == CONST_INT)
50090075Sobrien    mark_reg_pointer (XEXP (x, 0), BITS_PER_UNIT);
50118334Speter
50218334Speter  /* OLDX may have been the address on a temporary.  Update the address
50318334Speter     to indicate that X is now used.  */
50418334Speter  update_temp_slot_address (oldx, x);
50518334Speter
50618334Speter  return x;
50718334Speter}
50818334Speter
50918334Speter/* Like `memory_address' but pretend `flag_force_addr' is 0.  */
51018334Speter
51118334Speterrtx
512132718Skanmemory_address_noforce (enum machine_mode mode, rtx x)
51318334Speter{
51418334Speter  int ambient_force_addr = flag_force_addr;
51518334Speter  rtx val;
51618334Speter
51718334Speter  flag_force_addr = 0;
51818334Speter  val = memory_address (mode, x);
51918334Speter  flag_force_addr = ambient_force_addr;
52018334Speter  return val;
52118334Speter}
52218334Speter
52318334Speter/* Convert a mem ref into one with a valid memory address.
52418334Speter   Pass through anything else unchanged.  */
52518334Speter
52618334Speterrtx
527132718Skanvalidize_mem (rtx ref)
52818334Speter{
529169689Skan  if (!MEM_P (ref))
53018334Speter    return ref;
531169689Skan  ref = use_anchored_address (ref);
53290075Sobrien  if (! (flag_force_addr && CONSTANT_ADDRESS_P (XEXP (ref, 0)))
53390075Sobrien      && memory_address_p (GET_MODE (ref), XEXP (ref, 0)))
53418334Speter    return ref;
53590075Sobrien
53618334Speter  /* Don't alter REF itself, since that is probably a stack slot.  */
53790075Sobrien  return replace_equiv_address (ref, XEXP (ref, 0));
53818334Speter}
53990075Sobrien
540169689Skan/* If X is a memory reference to a member of an object block, try rewriting
541169689Skan   it to use an anchor instead.  Return the new memory reference on success
542169689Skan   and the old one on failure.  */
543117395Skan
54418334Speterrtx
545169689Skanuse_anchored_address (rtx x)
54618334Speter{
547169689Skan  rtx base;
548169689Skan  HOST_WIDE_INT offset;
549169689Skan
550169689Skan  if (!flag_section_anchors)
55118334Speter    return x;
55218334Speter
553169689Skan  if (!MEM_P (x))
554169689Skan    return x;
555169689Skan
556169689Skan  /* Split the address into a base and offset.  */
557169689Skan  base = XEXP (x, 0);
558169689Skan  offset = 0;
559169689Skan  if (GET_CODE (base) == CONST
560169689Skan      && GET_CODE (XEXP (base, 0)) == PLUS
561169689Skan      && GET_CODE (XEXP (XEXP (base, 0), 1)) == CONST_INT)
562169689Skan    {
563169689Skan      offset += INTVAL (XEXP (XEXP (base, 0), 1));
564169689Skan      base = XEXP (XEXP (base, 0), 0);
565169689Skan    }
566169689Skan
567169689Skan  /* Check whether BASE is suitable for anchors.  */
568169689Skan  if (GET_CODE (base) != SYMBOL_REF
569169689Skan      || !SYMBOL_REF_HAS_BLOCK_INFO_P (base)
570169689Skan      || SYMBOL_REF_ANCHOR_P (base)
571169689Skan      || SYMBOL_REF_BLOCK (base) == NULL
572169689Skan      || !targetm.use_anchors_for_symbol_p (base))
573169689Skan    return x;
574169689Skan
575169689Skan  /* Decide where BASE is going to be.  */
576169689Skan  place_block_symbol (base);
577169689Skan
578169689Skan  /* Get the anchor we need to use.  */
579169689Skan  offset += SYMBOL_REF_BLOCK_OFFSET (base);
580169689Skan  base = get_section_anchor (SYMBOL_REF_BLOCK (base), offset,
581169689Skan			     SYMBOL_REF_TLS_MODEL (base));
582169689Skan
583169689Skan  /* Work out the offset from the anchor.  */
584169689Skan  offset -= SYMBOL_REF_BLOCK_OFFSET (base);
585169689Skan
586169689Skan  /* If we're going to run a CSE pass, force the anchor into a register.
587169689Skan     We will then be able to reuse registers for several accesses, if the
588169689Skan     target costs say that that's worthwhile.  */
589169689Skan  if (!cse_not_expected)
590169689Skan    base = force_reg (GET_MODE (base), base);
591169689Skan
592169689Skan  return replace_equiv_address (x, plus_constant (base, offset));
59318334Speter}
59418334Speter
59518334Speter/* Copy the value or contents of X to a new temp reg and return that reg.  */
59618334Speter
59718334Speterrtx
598132718Skancopy_to_reg (rtx x)
59918334Speter{
60090075Sobrien  rtx temp = gen_reg_rtx (GET_MODE (x));
60196263Sobrien
60218334Speter  /* If not an operand, must be an address with PLUS and MULT so
60396263Sobrien     do the computation.  */
60418334Speter  if (! general_operand (x, VOIDmode))
60518334Speter    x = force_operand (x, temp);
60696263Sobrien
60718334Speter  if (x != temp)
60818334Speter    emit_move_insn (temp, x);
60918334Speter
61018334Speter  return temp;
61118334Speter}
61218334Speter
61318334Speter/* Like copy_to_reg but always give the new register mode Pmode
61418334Speter   in case X is a constant.  */
61518334Speter
61618334Speterrtx
617132718Skancopy_addr_to_reg (rtx x)
61818334Speter{
61918334Speter  return copy_to_mode_reg (Pmode, x);
62018334Speter}
62118334Speter
62218334Speter/* Like copy_to_reg but always give the new register mode MODE
62318334Speter   in case X is a constant.  */
62418334Speter
62518334Speterrtx
626132718Skancopy_to_mode_reg (enum machine_mode mode, rtx x)
62718334Speter{
62890075Sobrien  rtx temp = gen_reg_rtx (mode);
62996263Sobrien
63018334Speter  /* If not an operand, must be an address with PLUS and MULT so
63196263Sobrien     do the computation.  */
63218334Speter  if (! general_operand (x, VOIDmode))
63318334Speter    x = force_operand (x, temp);
63418334Speter
635169689Skan  gcc_assert (GET_MODE (x) == mode || GET_MODE (x) == VOIDmode);
63618334Speter  if (x != temp)
63718334Speter    emit_move_insn (temp, x);
63818334Speter  return temp;
63918334Speter}
64018334Speter
64118334Speter/* Load X into a register if it is not already one.
64218334Speter   Use mode MODE for the register.
64318334Speter   X should be valid for mode MODE, but it may be a constant which
64418334Speter   is valid for all integer modes; that's why caller must specify MODE.
64518334Speter
64618334Speter   The caller must not alter the value in the register we return,
64718334Speter   since we mark it as a "constant" register.  */
64818334Speter
64918334Speterrtx
650132718Skanforce_reg (enum machine_mode mode, rtx x)
65118334Speter{
65290075Sobrien  rtx temp, insn, set;
65318334Speter
654169689Skan  if (REG_P (x))
65518334Speter    return x;
65618334Speter
65796263Sobrien  if (general_operand (x, mode))
65896263Sobrien    {
65996263Sobrien      temp = gen_reg_rtx (mode);
66096263Sobrien      insn = emit_move_insn (temp, x);
66196263Sobrien    }
66296263Sobrien  else
66396263Sobrien    {
66496263Sobrien      temp = force_operand (x, NULL_RTX);
665169689Skan      if (REG_P (temp))
66696263Sobrien	insn = get_last_insn ();
66796263Sobrien      else
66896263Sobrien	{
66996263Sobrien	  rtx temp2 = gen_reg_rtx (mode);
67096263Sobrien	  insn = emit_move_insn (temp2, temp);
67196263Sobrien	  temp = temp2;
67296263Sobrien	}
67396263Sobrien    }
67496263Sobrien
67518334Speter  /* Let optimizers know that TEMP's value never changes
67618334Speter     and that X can be substituted for it.  Don't get confused
67718334Speter     if INSN set something else (such as a SUBREG of TEMP).  */
67818334Speter  if (CONSTANT_P (x)
67918334Speter      && (set = single_set (insn)) != 0
680132718Skan      && SET_DEST (set) == temp
681132718Skan      && ! rtx_equal_p (x, SET_SRC (set)))
68290075Sobrien    set_unique_reg_note (insn, REG_EQUAL, x);
68396263Sobrien
684169689Skan  /* Let optimizers know that TEMP is a pointer, and if so, the
685169689Skan     known alignment of that pointer.  */
686169689Skan  {
687169689Skan    unsigned align = 0;
688169689Skan    if (GET_CODE (x) == SYMBOL_REF)
689169689Skan      {
690169689Skan        align = BITS_PER_UNIT;
691169689Skan	if (SYMBOL_REF_DECL (x) && DECL_P (SYMBOL_REF_DECL (x)))
692169689Skan	  align = DECL_ALIGN (SYMBOL_REF_DECL (x));
693169689Skan      }
694169689Skan    else if (GET_CODE (x) == LABEL_REF)
695169689Skan      align = BITS_PER_UNIT;
696169689Skan    else if (GET_CODE (x) == CONST
697169689Skan	     && GET_CODE (XEXP (x, 0)) == PLUS
698169689Skan	     && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
699169689Skan	     && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
700169689Skan      {
701169689Skan	rtx s = XEXP (XEXP (x, 0), 0);
702169689Skan	rtx c = XEXP (XEXP (x, 0), 1);
703169689Skan	unsigned sa, ca;
704169689Skan
705169689Skan	sa = BITS_PER_UNIT;
706169689Skan	if (SYMBOL_REF_DECL (s) && DECL_P (SYMBOL_REF_DECL (s)))
707169689Skan	  sa = DECL_ALIGN (SYMBOL_REF_DECL (s));
708169689Skan
709169689Skan	ca = exact_log2 (INTVAL (c) & -INTVAL (c)) * BITS_PER_UNIT;
710169689Skan
711169689Skan	align = MIN (sa, ca);
712169689Skan      }
713169689Skan    else if (MEM_P (x) && MEM_POINTER (x))
714169689Skan      align = MEM_ALIGN (x);
715169689Skan
716169689Skan    if (align)
717169689Skan      mark_reg_pointer (temp, align);
718169689Skan  }
719169689Skan
72018334Speter  return temp;
72118334Speter}
72218334Speter
72318334Speter/* If X is a memory ref, copy its contents to a new temp reg and return
72418334Speter   that reg.  Otherwise, return X.  */
72518334Speter
72618334Speterrtx
727132718Skanforce_not_mem (rtx x)
72818334Speter{
72990075Sobrien  rtx temp;
73090075Sobrien
731169689Skan  if (!MEM_P (x) || GET_MODE (x) == BLKmode)
73218334Speter    return x;
73390075Sobrien
73418334Speter  temp = gen_reg_rtx (GET_MODE (x));
735169689Skan
736169689Skan  if (MEM_POINTER (x))
737169689Skan    REG_POINTER (temp) = 1;
738169689Skan
73918334Speter  emit_move_insn (temp, x);
74018334Speter  return temp;
74118334Speter}
74218334Speter
74318334Speter/* Copy X to TARGET (if it's nonzero and a reg)
74418334Speter   or to a new temp reg and return that reg.
74518334Speter   MODE is the mode to use for X in case it is a constant.  */
74618334Speter
74718334Speterrtx
748132718Skancopy_to_suggested_reg (rtx x, rtx target, enum machine_mode mode)
74918334Speter{
75090075Sobrien  rtx temp;
75118334Speter
752169689Skan  if (target && REG_P (target))
75318334Speter    temp = target;
75418334Speter  else
75518334Speter    temp = gen_reg_rtx (mode);
75618334Speter
75718334Speter  emit_move_insn (temp, x);
75818334Speter  return temp;
75918334Speter}
76018334Speter
76118334Speter/* Return the mode to use to store a scalar of TYPE and MODE.
76218334Speter   PUNSIGNEDP points to the signedness of the type and may be adjusted
76318334Speter   to show what signedness to use on extension operations.
76418334Speter
765117395Skan   FOR_CALL is nonzero if this call is promoting args for a call.  */
76618334Speter
767169689Skan#if defined(PROMOTE_MODE) && !defined(PROMOTE_FUNCTION_MODE)
768169689Skan#define PROMOTE_FUNCTION_MODE PROMOTE_MODE
769169689Skan#endif
770169689Skan
77118334Speterenum machine_mode
772132718Skanpromote_mode (tree type, enum machine_mode mode, int *punsignedp,
773132718Skan	      int for_call ATTRIBUTE_UNUSED)
77418334Speter{
77518334Speter  enum tree_code code = TREE_CODE (type);
77618334Speter  int unsignedp = *punsignedp;
77718334Speter
778169689Skan#ifndef PROMOTE_MODE
77918334Speter  if (! for_call)
78018334Speter    return mode;
78118334Speter#endif
78218334Speter
78318334Speter  switch (code)
78418334Speter    {
785169689Skan#ifdef PROMOTE_FUNCTION_MODE
786169689Skan    case INTEGER_TYPE:   case ENUMERAL_TYPE:   case BOOLEAN_TYPE:
787169689Skan    case REAL_TYPE:      case OFFSET_TYPE:
78818334Speter#ifdef PROMOTE_MODE
789169689Skan      if (for_call)
790169689Skan	{
791169689Skan#endif
792169689Skan	  PROMOTE_FUNCTION_MODE (mode, unsignedp, type);
793169689Skan#ifdef PROMOTE_MODE
794169689Skan	}
795169689Skan      else
796169689Skan	{
797169689Skan	  PROMOTE_MODE (mode, unsignedp, type);
798169689Skan	}
799169689Skan#endif
80018334Speter      break;
80118334Speter#endif
80218334Speter
80318334Speter#ifdef POINTERS_EXTEND_UNSIGNED
80450397Sobrien    case REFERENCE_TYPE:
80518334Speter    case POINTER_TYPE:
80618334Speter      mode = Pmode;
80718334Speter      unsignedp = POINTERS_EXTEND_UNSIGNED;
80818334Speter      break;
80918334Speter#endif
81096263Sobrien
81150397Sobrien    default:
81250397Sobrien      break;
81318334Speter    }
81418334Speter
81518334Speter  *punsignedp = unsignedp;
81618334Speter  return mode;
81718334Speter}
81818334Speter
81918334Speter/* Adjust the stack pointer by ADJUST (an rtx for a number of bytes).
82018334Speter   This pops when ADJUST is positive.  ADJUST need not be constant.  */
82118334Speter
82218334Spetervoid
823132718Skanadjust_stack (rtx adjust)
82418334Speter{
82518334Speter  rtx temp;
82618334Speter
82718334Speter  if (adjust == const0_rtx)
82818334Speter    return;
82918334Speter
83090075Sobrien  /* We expect all variable sized adjustments to be multiple of
83190075Sobrien     PREFERRED_STACK_BOUNDARY.  */
83290075Sobrien  if (GET_CODE (adjust) == CONST_INT)
83390075Sobrien    stack_pointer_delta -= INTVAL (adjust);
83490075Sobrien
83518334Speter  temp = expand_binop (Pmode,
83618334Speter#ifdef STACK_GROWS_DOWNWARD
83718334Speter		       add_optab,
83818334Speter#else
83918334Speter		       sub_optab,
84018334Speter#endif
84118334Speter		       stack_pointer_rtx, adjust, stack_pointer_rtx, 0,
84218334Speter		       OPTAB_LIB_WIDEN);
84318334Speter
84418334Speter  if (temp != stack_pointer_rtx)
84518334Speter    emit_move_insn (stack_pointer_rtx, temp);
84618334Speter}
84718334Speter
84818334Speter/* Adjust the stack pointer by minus ADJUST (an rtx for a number of bytes).
84918334Speter   This pushes when ADJUST is positive.  ADJUST need not be constant.  */
85018334Speter
85118334Spetervoid
852132718Skananti_adjust_stack (rtx adjust)
85318334Speter{
85418334Speter  rtx temp;
85518334Speter
85618334Speter  if (adjust == const0_rtx)
85718334Speter    return;
85818334Speter
85990075Sobrien  /* We expect all variable sized adjustments to be multiple of
86090075Sobrien     PREFERRED_STACK_BOUNDARY.  */
86190075Sobrien  if (GET_CODE (adjust) == CONST_INT)
86290075Sobrien    stack_pointer_delta += INTVAL (adjust);
86390075Sobrien
86418334Speter  temp = expand_binop (Pmode,
86518334Speter#ifdef STACK_GROWS_DOWNWARD
86618334Speter		       sub_optab,
86718334Speter#else
86818334Speter		       add_optab,
86918334Speter#endif
87018334Speter		       stack_pointer_rtx, adjust, stack_pointer_rtx, 0,
87118334Speter		       OPTAB_LIB_WIDEN);
87218334Speter
87318334Speter  if (temp != stack_pointer_rtx)
87418334Speter    emit_move_insn (stack_pointer_rtx, temp);
87518334Speter}
87618334Speter
87718334Speter/* Round the size of a block to be pushed up to the boundary required
87818334Speter   by this machine.  SIZE is the desired size, which need not be constant.  */
87918334Speter
880169689Skanstatic rtx
881132718Skanround_push (rtx size)
88218334Speter{
88352284Sobrien  int align = PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT;
884132718Skan
88518334Speter  if (align == 1)
88618334Speter    return size;
887132718Skan
88818334Speter  if (GET_CODE (size) == CONST_INT)
88918334Speter    {
890132718Skan      HOST_WIDE_INT new = (INTVAL (size) + align - 1) / align * align;
891132718Skan
89218334Speter      if (INTVAL (size) != new)
89318334Speter	size = GEN_INT (new);
89418334Speter    }
89518334Speter  else
89618334Speter    {
89718334Speter      /* CEIL_DIV_EXPR needs to worry about the addition overflowing,
89850397Sobrien	 but we know it can't.  So add ourselves and then do
89950397Sobrien	 TRUNC_DIV_EXPR.  */
90018334Speter      size = expand_binop (Pmode, add_optab, size, GEN_INT (align - 1),
90118334Speter			   NULL_RTX, 1, OPTAB_LIB_WIDEN);
90218334Speter      size = expand_divmod (0, TRUNC_DIV_EXPR, Pmode, size, GEN_INT (align),
90318334Speter			    NULL_RTX, 1);
90418334Speter      size = expand_mult (Pmode, size, GEN_INT (align), NULL_RTX, 1);
90518334Speter    }
906132718Skan
90718334Speter  return size;
90818334Speter}
90918334Speter
91018334Speter/* Save the stack pointer for the purpose in SAVE_LEVEL.  PSAVE is a pointer
91118334Speter   to a previously-created save area.  If no save area has been allocated,
91218334Speter   this function will allocate one.  If a save area is specified, it
91318334Speter   must be of the proper mode.
91418334Speter
91518334Speter   The insns are emitted after insn AFTER, if nonzero, otherwise the insns
91618334Speter   are emitted at the current position.  */
91718334Speter
91818334Spetervoid
919132718Skanemit_stack_save (enum save_level save_level, rtx *psave, rtx after)
92018334Speter{
92118334Speter  rtx sa = *psave;
92218334Speter  /* The default is that we use a move insn and save in a Pmode object.  */
923132718Skan  rtx (*fcn) (rtx, rtx) = gen_move_insn;
92450397Sobrien  enum machine_mode mode = STACK_SAVEAREA_MODE (save_level);
92518334Speter
92618334Speter  /* See if this machine has anything special to do for this kind of save.  */
92718334Speter  switch (save_level)
92818334Speter    {
92918334Speter#ifdef HAVE_save_stack_block
93018334Speter    case SAVE_BLOCK:
93118334Speter      if (HAVE_save_stack_block)
93250397Sobrien	fcn = gen_save_stack_block;
93318334Speter      break;
93418334Speter#endif
93518334Speter#ifdef HAVE_save_stack_function
93618334Speter    case SAVE_FUNCTION:
93718334Speter      if (HAVE_save_stack_function)
93850397Sobrien	fcn = gen_save_stack_function;
93918334Speter      break;
94018334Speter#endif
94118334Speter#ifdef HAVE_save_stack_nonlocal
94218334Speter    case SAVE_NONLOCAL:
94318334Speter      if (HAVE_save_stack_nonlocal)
94450397Sobrien	fcn = gen_save_stack_nonlocal;
94518334Speter      break;
94618334Speter#endif
94750397Sobrien    default:
94850397Sobrien      break;
94918334Speter    }
95018334Speter
95118334Speter  /* If there is no save area and we have to allocate one, do so.  Otherwise
95218334Speter     verify the save area is the proper mode.  */
95318334Speter
95418334Speter  if (sa == 0)
95518334Speter    {
95618334Speter      if (mode != VOIDmode)
95718334Speter	{
95818334Speter	  if (save_level == SAVE_NONLOCAL)
95918334Speter	    *psave = sa = assign_stack_local (mode, GET_MODE_SIZE (mode), 0);
96018334Speter	  else
96118334Speter	    *psave = sa = gen_reg_rtx (mode);
96218334Speter	}
96318334Speter    }
96418334Speter
96518334Speter  if (after)
96618334Speter    {
96718334Speter      rtx seq;
96818334Speter
96918334Speter      start_sequence ();
970146895Skan      do_pending_stack_adjust ();
97118334Speter      /* We must validize inside the sequence, to ensure that any instructions
97218334Speter	 created by the validize call also get moved to the right place.  */
97318334Speter      if (sa != 0)
97418334Speter	sa = validize_mem (sa);
97518334Speter      emit_insn (fcn (sa, stack_pointer_rtx));
976117395Skan      seq = get_insns ();
97718334Speter      end_sequence ();
97818334Speter      emit_insn_after (seq, after);
97918334Speter    }
98018334Speter  else
98118334Speter    {
982146895Skan      do_pending_stack_adjust ();
98318334Speter      if (sa != 0)
98418334Speter	sa = validize_mem (sa);
98518334Speter      emit_insn (fcn (sa, stack_pointer_rtx));
98618334Speter    }
98718334Speter}
98818334Speter
98918334Speter/* Restore the stack pointer for the purpose in SAVE_LEVEL.  SA is the save
99096263Sobrien   area made by emit_stack_save.  If it is zero, we have nothing to do.
99118334Speter
99296263Sobrien   Put any emitted insns after insn AFTER, if nonzero, otherwise at
99318334Speter   current position.  */
99418334Speter
99518334Spetervoid
996132718Skanemit_stack_restore (enum save_level save_level, rtx sa, rtx after)
99718334Speter{
99818334Speter  /* The default is that we use a move insn.  */
999132718Skan  rtx (*fcn) (rtx, rtx) = gen_move_insn;
100018334Speter
100118334Speter  /* See if this machine has anything special to do for this kind of save.  */
100218334Speter  switch (save_level)
100318334Speter    {
100418334Speter#ifdef HAVE_restore_stack_block
100518334Speter    case SAVE_BLOCK:
100618334Speter      if (HAVE_restore_stack_block)
100718334Speter	fcn = gen_restore_stack_block;
100818334Speter      break;
100918334Speter#endif
101018334Speter#ifdef HAVE_restore_stack_function
101118334Speter    case SAVE_FUNCTION:
101218334Speter      if (HAVE_restore_stack_function)
101318334Speter	fcn = gen_restore_stack_function;
101418334Speter      break;
101518334Speter#endif
101618334Speter#ifdef HAVE_restore_stack_nonlocal
101718334Speter    case SAVE_NONLOCAL:
101818334Speter      if (HAVE_restore_stack_nonlocal)
101918334Speter	fcn = gen_restore_stack_nonlocal;
102018334Speter      break;
102118334Speter#endif
102250397Sobrien    default:
102350397Sobrien      break;
102418334Speter    }
102518334Speter
102618334Speter  if (sa != 0)
1027117395Skan    {
1028117395Skan      sa = validize_mem (sa);
1029117395Skan      /* These clobbers prevent the scheduler from moving
1030117395Skan	 references to variable arrays below the code
1031117395Skan	 that deletes (pops) the arrays.  */
1032117395Skan      emit_insn (gen_rtx_CLOBBER (VOIDmode,
1033132718Skan		    gen_rtx_MEM (BLKmode,
1034117395Skan			gen_rtx_SCRATCH (VOIDmode))));
1035117395Skan      emit_insn (gen_rtx_CLOBBER (VOIDmode,
1036117395Skan		    gen_rtx_MEM (BLKmode, stack_pointer_rtx)));
1037117395Skan    }
103818334Speter
1039146895Skan  discard_pending_stack_adjust ();
1040146895Skan
104118334Speter  if (after)
104218334Speter    {
104318334Speter      rtx seq;
104418334Speter
104518334Speter      start_sequence ();
104618334Speter      emit_insn (fcn (stack_pointer_rtx, sa));
1047117395Skan      seq = get_insns ();
104818334Speter      end_sequence ();
104918334Speter      emit_insn_after (seq, after);
105018334Speter    }
105118334Speter  else
105218334Speter    emit_insn (fcn (stack_pointer_rtx, sa));
105318334Speter}
105450397Sobrien
1055169689Skan/* Invoke emit_stack_save on the nonlocal_goto_save_area for the current
1056169689Skan   function.  This function should be called whenever we allocate or
1057169689Skan   deallocate dynamic stack space.  */
1058169689Skan
105950397Sobrienvoid
1060169689Skanupdate_nonlocal_goto_save_area (void)
106150397Sobrien{
1062169689Skan  tree t_save;
1063169689Skan  rtx r_save;
106450397Sobrien
1065169689Skan  /* The nonlocal_goto_save_area object is an array of N pointers.  The
1066169689Skan     first one is used for the frame pointer save; the rest are sized by
1067169689Skan     STACK_SAVEAREA_MODE.  Create a reference to array index 1, the first
1068169689Skan     of the stack save area slots.  */
1069169689Skan  t_save = build4 (ARRAY_REF, ptr_type_node, cfun->nonlocal_goto_save_area,
1070169689Skan		   integer_one_node, NULL_TREE, NULL_TREE);
1071169689Skan  r_save = expand_expr (t_save, NULL_RTX, VOIDmode, EXPAND_WRITE);
107250397Sobrien
1073169689Skan  emit_stack_save (SAVE_NONLOCAL, &r_save, NULL_RTX);
107450397Sobrien}
1075169689Skan
107618334Speter/* Return an rtx representing the address of an area of memory dynamically
107718334Speter   pushed on the stack.  This region of memory is always aligned to
107818334Speter   a multiple of BIGGEST_ALIGNMENT.
107918334Speter
108018334Speter   Any required stack pointer alignment is preserved.
108118334Speter
108218334Speter   SIZE is an rtx representing the size of the area.
108318334Speter   TARGET is a place in which the address can be placed.
108418334Speter
108518334Speter   KNOWN_ALIGN is the alignment (in bits) that we know SIZE has.  */
108618334Speter
108718334Speterrtx
1088132718Skanallocate_dynamic_stack_space (rtx size, rtx target, int known_align)
108918334Speter{
109018334Speter  /* If we're asking for zero bytes, it doesn't matter what we point
109118334Speter     to since we can't dereference it.  But return a reasonable
109218334Speter     address anyway.  */
109318334Speter  if (size == const0_rtx)
109418334Speter    return virtual_stack_dynamic_rtx;
109518334Speter
109618334Speter  /* Otherwise, show we're calling alloca or equivalent.  */
109718334Speter  current_function_calls_alloca = 1;
109818334Speter
109918334Speter  /* Ensure the size is in the proper mode.  */
110018334Speter  if (GET_MODE (size) != VOIDmode && GET_MODE (size) != Pmode)
110118334Speter    size = convert_to_mode (Pmode, size, 1);
110218334Speter
110390075Sobrien  /* We can't attempt to minimize alignment necessary, because we don't
110490075Sobrien     know the final value of preferred_stack_boundary yet while executing
110590075Sobrien     this code.  */
110690075Sobrien  cfun->preferred_stack_boundary = PREFERRED_STACK_BOUNDARY;
110790075Sobrien
110818334Speter  /* We will need to ensure that the address we return is aligned to
110918334Speter     BIGGEST_ALIGNMENT.  If STACK_DYNAMIC_OFFSET is defined, we don't
111096263Sobrien     always know its final value at this point in the compilation (it
111118334Speter     might depend on the size of the outgoing parameter lists, for
111218334Speter     example), so we must align the value to be returned in that case.
1113117395Skan     (Note that STACK_DYNAMIC_OFFSET will have a default nonzero value if
111418334Speter     STACK_POINTER_OFFSET or ACCUMULATE_OUTGOING_ARGS are defined).
111518334Speter     We must also do an alignment operation on the returned value if
111618334Speter     the stack pointer alignment is less strict that BIGGEST_ALIGNMENT.
111718334Speter
111818334Speter     If we have to align, we must leave space in SIZE for the hole
111918334Speter     that might result from the alignment operation.  */
112018334Speter
112190075Sobrien#if defined (STACK_DYNAMIC_OFFSET) || defined (STACK_POINTER_OFFSET)
112218334Speter#define MUST_ALIGN 1
112318334Speter#else
112452284Sobrien#define MUST_ALIGN (PREFERRED_STACK_BOUNDARY < BIGGEST_ALIGNMENT)
112518334Speter#endif
112618334Speter
112718334Speter  if (MUST_ALIGN)
112890075Sobrien    size
112996263Sobrien      = force_operand (plus_constant (size,
113090075Sobrien				      BIGGEST_ALIGNMENT / BITS_PER_UNIT - 1),
113190075Sobrien		       NULL_RTX);
113218334Speter
113318334Speter#ifdef SETJMP_VIA_SAVE_AREA
113418334Speter  /* If setjmp restores regs from a save area in the stack frame,
113518334Speter     avoid clobbering the reg save area.  Note that the offset of
113618334Speter     virtual_incoming_args_rtx includes the preallocated stack args space.
113718334Speter     It would be no problem to clobber that, but it's on the wrong side
1138169689Skan     of the old save area.
113950397Sobrien
1140169689Skan     What used to happen is that, since we did not know for sure
1141169689Skan     whether setjmp() was invoked until after RTL generation, we
1142169689Skan     would use reg notes to store the "optimized" size and fix things
1143169689Skan     up later.  These days we know this information before we ever
1144169689Skan     start building RTL so the reg notes are unnecessary.  */
1145169689Skan  if (!current_function_calls_setjmp)
1146169689Skan    {
1147169689Skan      int align = PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT;
114850397Sobrien
1149169689Skan      /* ??? Code below assumes that the save area needs maximal
1150169689Skan	 alignment.  This constraint may be too strong.  */
1151169689Skan      gcc_assert (PREFERRED_STACK_BOUNDARY == BIGGEST_ALIGNMENT);
115250397Sobrien
1153169689Skan      if (GET_CODE (size) == CONST_INT)
1154169689Skan	{
1155169689Skan	  HOST_WIDE_INT new = INTVAL (size) / align * align;
115650397Sobrien
1157169689Skan	  if (INTVAL (size) != new)
1158169689Skan	    size = GEN_INT (new);
1159169689Skan	}
1160169689Skan      else
1161169689Skan	{
1162169689Skan	  /* Since we know overflow is not possible, we avoid using
1163169689Skan	     CEIL_DIV_EXPR and use TRUNC_DIV_EXPR instead.  */
1164169689Skan	  size = expand_divmod (0, TRUNC_DIV_EXPR, Pmode, size,
1165169689Skan				GEN_INT (align), NULL_RTX, 1);
1166169689Skan	  size = expand_mult (Pmode, size,
1167169689Skan			      GEN_INT (align), NULL_RTX, 1);
1168169689Skan	}
1169169689Skan    }
1170169689Skan  else
1171169689Skan    {
1172169689Skan      rtx dynamic_offset
1173169689Skan	= expand_binop (Pmode, sub_optab, virtual_stack_dynamic_rtx,
1174169689Skan			stack_pointer_rtx, NULL_RTX, 1, OPTAB_LIB_WIDEN);
117550397Sobrien
1176169689Skan      size = expand_binop (Pmode, add_optab, size, dynamic_offset,
1177169689Skan			   NULL_RTX, 1, OPTAB_LIB_WIDEN);
1178169689Skan    }
117918334Speter#endif /* SETJMP_VIA_SAVE_AREA */
118018334Speter
118118334Speter  /* Round the size to a multiple of the required stack alignment.
118218334Speter     Since the stack if presumed to be rounded before this allocation,
118318334Speter     this will maintain the required alignment.
118418334Speter
118518334Speter     If the stack grows downward, we could save an insn by subtracting
118618334Speter     SIZE from the stack pointer and then aligning the stack pointer.
118718334Speter     The problem with this is that the stack pointer may be unaligned
118818334Speter     between the execution of the subtraction and alignment insns and
118918334Speter     some machines do not allow this.  Even on those that do, some
119018334Speter     signal handlers malfunction if a signal should occur between those
119118334Speter     insns.  Since this is an extremely rare event, we have no reliable
119218334Speter     way of knowing which systems have this problem.  So we avoid even
119318334Speter     momentarily mis-aligning the stack.  */
119418334Speter
119518334Speter  /* If we added a variable amount to SIZE,
119618334Speter     we can no longer assume it is aligned.  */
119718334Speter#if !defined (SETJMP_VIA_SAVE_AREA)
119852284Sobrien  if (MUST_ALIGN || known_align % PREFERRED_STACK_BOUNDARY != 0)
119918334Speter#endif
120018334Speter    size = round_push (size);
120118334Speter
120218334Speter  do_pending_stack_adjust ();
120318334Speter
120490075Sobrien /* We ought to be called always on the toplevel and stack ought to be aligned
120590075Sobrien    properly.  */
1206169689Skan  gcc_assert (!(stack_pointer_delta
1207169689Skan		% (PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT)));
120890075Sobrien
120950397Sobrien  /* If needed, check that we have the required amount of stack.  Take into
121050397Sobrien     account what has already been checked.  */
121150397Sobrien  if (flag_stack_check && ! STACK_CHECK_BUILTIN)
121250397Sobrien    probe_stack_range (STACK_CHECK_MAX_FRAME_SIZE + STACK_CHECK_PROTECT, size);
121350397Sobrien
121490075Sobrien  /* Don't use a TARGET that isn't a pseudo or is the wrong mode.  */
1215169689Skan  if (target == 0 || !REG_P (target)
121690075Sobrien      || REGNO (target) < FIRST_PSEUDO_REGISTER
121790075Sobrien      || GET_MODE (target) != Pmode)
121818334Speter    target = gen_reg_rtx (Pmode);
121918334Speter
122090075Sobrien  mark_reg_pointer (target, known_align);
122118334Speter
122218334Speter  /* Perform the required allocation from the stack.  Some systems do
122318334Speter     this differently than simply incrementing/decrementing from the
122450397Sobrien     stack pointer, such as acquiring the space by calling malloc().  */
122518334Speter#ifdef HAVE_allocate_stack
122618334Speter  if (HAVE_allocate_stack)
122718334Speter    {
122850397Sobrien      enum machine_mode mode = STACK_SIZE_MODE;
122990075Sobrien      insn_operand_predicate_fn pred;
123018334Speter
123190075Sobrien      /* We don't have to check against the predicate for operand 0 since
123290075Sobrien	 TARGET is known to be a pseudo of the proper mode, which must
123390075Sobrien	 be valid for the operand.  For operand 1, convert to the
123490075Sobrien	 proper mode and validate.  */
123590075Sobrien      if (mode == VOIDmode)
123690075Sobrien	mode = insn_data[(int) CODE_FOR_allocate_stack].operand[1].mode;
123790075Sobrien
123890075Sobrien      pred = insn_data[(int) CODE_FOR_allocate_stack].operand[1].predicate;
123990075Sobrien      if (pred && ! ((*pred) (size, mode)))
1240132718Skan	size = copy_to_mode_reg (mode, convert_to_mode (mode, size, 1));
124118334Speter
124250397Sobrien      emit_insn (gen_allocate_stack (target, size));
124318334Speter    }
124418334Speter  else
124518334Speter#endif
124618334Speter    {
124750397Sobrien#ifndef STACK_GROWS_DOWNWARD
124850397Sobrien      emit_move_insn (target, virtual_stack_dynamic_rtx);
124950397Sobrien#endif
125090075Sobrien
125190075Sobrien      /* Check stack bounds if necessary.  */
125290075Sobrien      if (current_function_limit_stack)
125390075Sobrien	{
125490075Sobrien	  rtx available;
125590075Sobrien	  rtx space_available = gen_label_rtx ();
125690075Sobrien#ifdef STACK_GROWS_DOWNWARD
125796263Sobrien	  available = expand_binop (Pmode, sub_optab,
125890075Sobrien				    stack_pointer_rtx, stack_limit_rtx,
125990075Sobrien				    NULL_RTX, 1, OPTAB_WIDEN);
126090075Sobrien#else
126196263Sobrien	  available = expand_binop (Pmode, sub_optab,
126290075Sobrien				    stack_limit_rtx, stack_pointer_rtx,
126390075Sobrien				    NULL_RTX, 1, OPTAB_WIDEN);
126490075Sobrien#endif
126590075Sobrien	  emit_cmp_and_jump_insns (available, size, GEU, NULL_RTX, Pmode, 1,
126690075Sobrien				   space_available);
126790075Sobrien#ifdef HAVE_trap
126890075Sobrien	  if (HAVE_trap)
126990075Sobrien	    emit_insn (gen_trap ());
127090075Sobrien	  else
127190075Sobrien#endif
127290075Sobrien	    error ("stack limits not supported on this target");
127390075Sobrien	  emit_barrier ();
127490075Sobrien	  emit_label (space_available);
127590075Sobrien	}
127690075Sobrien
127718334Speter      anti_adjust_stack (size);
127818334Speter
127918334Speter#ifdef STACK_GROWS_DOWNWARD
128096263Sobrien      emit_move_insn (target, virtual_stack_dynamic_rtx);
128118334Speter#endif
128250397Sobrien    }
128318334Speter
128418334Speter  if (MUST_ALIGN)
128518334Speter    {
128618334Speter      /* CEIL_DIV_EXPR needs to worry about the addition overflowing,
128750397Sobrien	 but we know it can't.  So add ourselves and then do
128850397Sobrien	 TRUNC_DIV_EXPR.  */
128918334Speter      target = expand_binop (Pmode, add_optab, target,
129018334Speter			     GEN_INT (BIGGEST_ALIGNMENT / BITS_PER_UNIT - 1),
129118334Speter			     NULL_RTX, 1, OPTAB_LIB_WIDEN);
129218334Speter      target = expand_divmod (0, TRUNC_DIV_EXPR, Pmode, target,
129318334Speter			      GEN_INT (BIGGEST_ALIGNMENT / BITS_PER_UNIT),
129418334Speter			      NULL_RTX, 1);
129518334Speter      target = expand_mult (Pmode, target,
129618334Speter			    GEN_INT (BIGGEST_ALIGNMENT / BITS_PER_UNIT),
129718334Speter			    NULL_RTX, 1);
129818334Speter    }
129996263Sobrien
130018334Speter  /* Record the new stack level for nonlocal gotos.  */
1301169689Skan  if (cfun->nonlocal_goto_save_area != 0)
1302169689Skan    update_nonlocal_goto_save_area ();
130318334Speter
130418334Speter  return target;
130518334Speter}
130618334Speter
130796263Sobrien/* A front end may want to override GCC's stack checking by providing a
130890075Sobrien   run-time routine to call to check the stack, so provide a mechanism for
130990075Sobrien   calling that routine.  */
131090075Sobrien
1311117395Skanstatic GTY(()) rtx stack_check_libfunc;
131290075Sobrien
131390075Sobrienvoid
1314132718Skanset_stack_check_libfunc (rtx libfunc)
131590075Sobrien{
131690075Sobrien  stack_check_libfunc = libfunc;
131790075Sobrien}
131890075Sobrien
131950397Sobrien/* Emit one stack probe at ADDRESS, an address within the stack.  */
132050397Sobrien
132150397Sobrienstatic void
1322132718Skanemit_stack_probe (rtx address)
132350397Sobrien{
132450397Sobrien  rtx memref = gen_rtx_MEM (word_mode, address);
132550397Sobrien
132650397Sobrien  MEM_VOLATILE_P (memref) = 1;
132750397Sobrien
132850397Sobrien  if (STACK_CHECK_PROBE_LOAD)
132950397Sobrien    emit_move_insn (gen_reg_rtx (word_mode), memref);
133050397Sobrien  else
133150397Sobrien    emit_move_insn (memref, const0_rtx);
133250397Sobrien}
133350397Sobrien
133496263Sobrien/* Probe a range of stack addresses from FIRST to FIRST+SIZE, inclusive.
133550397Sobrien   FIRST is a constant and size is a Pmode RTX.  These are offsets from the
133650397Sobrien   current stack pointer.  STACK_GROWS_DOWNWARD says whether to add or
133750397Sobrien   subtract from the stack.  If SIZE is constant, this is done
133850397Sobrien   with a fixed number of probes.  Otherwise, we must make a loop.  */
133950397Sobrien
134050397Sobrien#ifdef STACK_GROWS_DOWNWARD
134150397Sobrien#define STACK_GROW_OP MINUS
134250397Sobrien#else
134350397Sobrien#define STACK_GROW_OP PLUS
134450397Sobrien#endif
134550397Sobrien
134650397Sobrienvoid
1347132718Skanprobe_stack_range (HOST_WIDE_INT first, rtx size)
134850397Sobrien{
134990075Sobrien  /* First ensure SIZE is Pmode.  */
135090075Sobrien  if (GET_MODE (size) != VOIDmode && GET_MODE (size) != Pmode)
135190075Sobrien    size = convert_to_mode (Pmode, size, 1);
135290075Sobrien
135390075Sobrien  /* Next see if the front end has set up a function for us to call to
135490075Sobrien     check the stack.  */
135590075Sobrien  if (stack_check_libfunc != 0)
135690075Sobrien    {
135790075Sobrien      rtx addr = memory_address (QImode,
1358117395Skan				 gen_rtx_fmt_ee (STACK_GROW_OP, Pmode,
1359117395Skan					         stack_pointer_rtx,
1360117395Skan					         plus_constant (size, first)));
136190075Sobrien
1362132718Skan      addr = convert_memory_address (ptr_mode, addr);
136390075Sobrien      emit_library_call (stack_check_libfunc, LCT_NORMAL, VOIDmode, 1, addr,
136490075Sobrien			 ptr_mode);
136590075Sobrien    }
136690075Sobrien
136790075Sobrien  /* Next see if we have an insn to check the stack.  Use it if so.  */
136850397Sobrien#ifdef HAVE_check_stack
136990075Sobrien  else if (HAVE_check_stack)
137050397Sobrien    {
137190075Sobrien      insn_operand_predicate_fn pred;
137250397Sobrien      rtx last_addr
1373117395Skan	= force_operand (gen_rtx_fmt_ee (STACK_GROW_OP, Pmode,
1374117395Skan					 stack_pointer_rtx,
1375117395Skan					 plus_constant (size, first)),
137650397Sobrien			 NULL_RTX);
137750397Sobrien
137890075Sobrien      pred = insn_data[(int) CODE_FOR_check_stack].operand[0].predicate;
137990075Sobrien      if (pred && ! ((*pred) (last_addr, Pmode)))
138090075Sobrien	last_addr = copy_to_mode_reg (Pmode, last_addr);
138150397Sobrien
138290075Sobrien      emit_insn (gen_check_stack (last_addr));
138350397Sobrien    }
138450397Sobrien#endif
138550397Sobrien
138650397Sobrien  /* If we have to generate explicit probes, see if we have a constant
138750397Sobrien     small number of them to generate.  If so, that's the easy case.  */
138890075Sobrien  else if (GET_CODE (size) == CONST_INT
138990075Sobrien	   && INTVAL (size) < 10 * STACK_CHECK_PROBE_INTERVAL)
139050397Sobrien    {
139150397Sobrien      HOST_WIDE_INT offset;
139250397Sobrien
139350397Sobrien      /* Start probing at FIRST + N * STACK_CHECK_PROBE_INTERVAL
139450397Sobrien	 for values of N from 1 until it exceeds LAST.  If only one
139550397Sobrien	 probe is needed, this will not generate any code.  Then probe
139650397Sobrien	 at LAST.  */
139750397Sobrien      for (offset = first + STACK_CHECK_PROBE_INTERVAL;
139850397Sobrien	   offset < INTVAL (size);
139950397Sobrien	   offset = offset + STACK_CHECK_PROBE_INTERVAL)
140050397Sobrien	emit_stack_probe (gen_rtx_fmt_ee (STACK_GROW_OP, Pmode,
140150397Sobrien					  stack_pointer_rtx,
140250397Sobrien					  GEN_INT (offset)));
140350397Sobrien
140450397Sobrien      emit_stack_probe (gen_rtx_fmt_ee (STACK_GROW_OP, Pmode,
140550397Sobrien					stack_pointer_rtx,
140650397Sobrien					plus_constant (size, first)));
140750397Sobrien    }
140850397Sobrien
140950397Sobrien  /* In the variable case, do the same as above, but in a loop.  We emit loop
141050397Sobrien     notes so that loop optimization can be done.  */
141150397Sobrien  else
141250397Sobrien    {
141350397Sobrien      rtx test_addr
141450397Sobrien	= force_operand (gen_rtx_fmt_ee (STACK_GROW_OP, Pmode,
141550397Sobrien					 stack_pointer_rtx,
141650397Sobrien					 GEN_INT (first + STACK_CHECK_PROBE_INTERVAL)),
141750397Sobrien			 NULL_RTX);
141850397Sobrien      rtx last_addr
141950397Sobrien	= force_operand (gen_rtx_fmt_ee (STACK_GROW_OP, Pmode,
142050397Sobrien					 stack_pointer_rtx,
142150397Sobrien					 plus_constant (size, first)),
142250397Sobrien			 NULL_RTX);
142350397Sobrien      rtx incr = GEN_INT (STACK_CHECK_PROBE_INTERVAL);
142450397Sobrien      rtx loop_lab = gen_label_rtx ();
142550397Sobrien      rtx test_lab = gen_label_rtx ();
142650397Sobrien      rtx end_lab = gen_label_rtx ();
142750397Sobrien      rtx temp;
142850397Sobrien
1429169689Skan      if (!REG_P (test_addr)
143050397Sobrien	  || REGNO (test_addr) < FIRST_PSEUDO_REGISTER)
143150397Sobrien	test_addr = force_reg (Pmode, test_addr);
143250397Sobrien
143350397Sobrien      emit_jump (test_lab);
143450397Sobrien
143550397Sobrien      emit_label (loop_lab);
143650397Sobrien      emit_stack_probe (test_addr);
143750397Sobrien
143850397Sobrien#ifdef STACK_GROWS_DOWNWARD
143950397Sobrien#define CMP_OPCODE GTU
144050397Sobrien      temp = expand_binop (Pmode, sub_optab, test_addr, incr, test_addr,
144150397Sobrien			   1, OPTAB_WIDEN);
144250397Sobrien#else
144350397Sobrien#define CMP_OPCODE LTU
144450397Sobrien      temp = expand_binop (Pmode, add_optab, test_addr, incr, test_addr,
144550397Sobrien			   1, OPTAB_WIDEN);
144650397Sobrien#endif
144750397Sobrien
1448169689Skan      gcc_assert (temp == test_addr);
144950397Sobrien
145050397Sobrien      emit_label (test_lab);
145152284Sobrien      emit_cmp_and_jump_insns (test_addr, last_addr, CMP_OPCODE,
145290075Sobrien			       NULL_RTX, Pmode, 1, loop_lab);
145350397Sobrien      emit_jump (end_lab);
145450397Sobrien      emit_label (end_lab);
145550397Sobrien
145650397Sobrien      emit_stack_probe (last_addr);
145750397Sobrien    }
145850397Sobrien}
145950397Sobrien
146018334Speter/* Return an rtx representing the register or memory location
146118334Speter   in which a scalar value of data type VALTYPE
146218334Speter   was returned by a function call to function FUNC.
1463169689Skan   FUNC is a FUNCTION_DECL, FNTYPE a FUNCTION_TYPE node if the precise
1464169689Skan   function is known, otherwise 0.
146590075Sobrien   OUTGOING is 1 if on a machine with register windows this function
146690075Sobrien   should return the register in which the function will put its result
146790075Sobrien   and 0 otherwise.  */
146818334Speter
146918334Speterrtx
1470169689Skanhard_function_value (tree valtype, tree func, tree fntype,
1471132718Skan		     int outgoing ATTRIBUTE_UNUSED)
147218334Speter{
147390075Sobrien  rtx val;
147490075Sobrien
1475169689Skan  val = targetm.calls.function_value (valtype, func ? func : fntype, outgoing);
147690075Sobrien
1477169689Skan  if (REG_P (val)
147818334Speter      && GET_MODE (val) == BLKmode)
147918334Speter    {
148090075Sobrien      unsigned HOST_WIDE_INT bytes = int_size_in_bytes (valtype);
148118334Speter      enum machine_mode tmpmode;
148290075Sobrien
148396263Sobrien      /* int_size_in_bytes can return -1.  We don't need a check here
1484169689Skan	 since the value of bytes will then be large enough that no
1485169689Skan	 mode will match anyway.  */
148696263Sobrien
148718334Speter      for (tmpmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
1488117395Skan	   tmpmode != VOIDmode;
1489117395Skan	   tmpmode = GET_MODE_WIDER_MODE (tmpmode))
1490117395Skan	{
1491117395Skan	  /* Have we found a large enough mode?  */
1492117395Skan	  if (GET_MODE_SIZE (tmpmode) >= bytes)
1493117395Skan	    break;
1494117395Skan	}
149518334Speter
149618334Speter      /* No suitable mode found.  */
1497169689Skan      gcc_assert (tmpmode != VOIDmode);
149818334Speter
149918334Speter      PUT_MODE (val, tmpmode);
150096263Sobrien    }
150118334Speter  return val;
150218334Speter}
150318334Speter
150418334Speter/* Return an rtx representing the register or memory location
150518334Speter   in which a scalar value of mode MODE was returned by a library call.  */
150618334Speter
150718334Speterrtx
1508132718Skanhard_libcall_value (enum machine_mode mode)
150918334Speter{
151018334Speter  return LIBCALL_VALUE (mode);
151118334Speter}
151218334Speter
151318334Speter/* Look up the tree code for a given rtx code
151418334Speter   to provide the arithmetic operation for REAL_ARITHMETIC.
151518334Speter   The function returns an int because the caller may not know
151618334Speter   what `enum tree_code' means.  */
151718334Speter
151818334Speterint
1519132718Skanrtx_to_tree_code (enum rtx_code code)
152018334Speter{
152118334Speter  enum tree_code tcode;
152218334Speter
152318334Speter  switch (code)
152418334Speter    {
152518334Speter    case PLUS:
152618334Speter      tcode = PLUS_EXPR;
152718334Speter      break;
152818334Speter    case MINUS:
152918334Speter      tcode = MINUS_EXPR;
153018334Speter      break;
153118334Speter    case MULT:
153218334Speter      tcode = MULT_EXPR;
153318334Speter      break;
153418334Speter    case DIV:
153518334Speter      tcode = RDIV_EXPR;
153618334Speter      break;
153718334Speter    case SMIN:
153818334Speter      tcode = MIN_EXPR;
153918334Speter      break;
154018334Speter    case SMAX:
154118334Speter      tcode = MAX_EXPR;
154218334Speter      break;
154318334Speter    default:
154418334Speter      tcode = LAST_AND_UNUSED_TREE_CODE;
154518334Speter      break;
154618334Speter    }
154718334Speter  return ((int) tcode);
154818334Speter}
1549117395Skan
1550117395Skan#include "gt-explow.h"
1551