/* Expand the basic unary and binary arithmetic operations, for GNU compiler.
- Copyright (C) 1987, 88, 92, 93, 94, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
This file is part of GNU CC.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
#include "config.h"
/* Tables of patterns for extending one integer mode to another. */
enum insn_code extendtab[MAX_MACHINE_MODE][MAX_MACHINE_MODE][2];
-/* Tables of patterns for converting between fixed and floating point. */
+/* Tables of patterns for converting between fixed and floating point. */
enum insn_code fixtab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2];
enum insn_code fixtrunctab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2];
enum insn_code floattab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2];
rtx memset_libfunc;
rtx bzero_libfunc;
+rtx throw_libfunc;
+
rtx eqhf2_libfunc;
rtx nehf2_libfunc;
rtx gthf2_libfunc;
temp = gen_reg_rtx (mode);
/* If it is a commutative operator and the modes would match
- if we would swap the operands, we can save the conversions. */
+ if we would swap the operands, we can save the conversions. */
if (commutative_op)
{
if (GET_MODE (op0) != mode0 && GET_MODE (op1) != mode1
/* If the target is the same as one of the inputs, don't use it. This
prevents problems with the REG_EQUAL note. */
- if (target == op0 || target == op1 || GET_CODE (target) != REG)
+ if (target == op0 || target == op1
+ || (target != 0 && GET_CODE (target) != REG))
target = 0;
/* Multiply the two lower words to get a double-word product.
op0 = protect_from_queue (op0, 0);
- if (flag_force_mem)
+ /* Sign extension from memory is often done specially on RISC
+ machines, so forcing into a register here can pessimize code. */
+ if (flag_force_mem && code != SIGN_EXTEND)
op0 = force_not_mem (op0);
/* Now, if insn does not accept our operands, put them into pseudos. */
else
#endif
{
+ rtx result;
+
#ifdef TARGET_MEM_FUNCTIONS
emit_library_call (memcmp_libfunc, 0,
TYPE_MODE (integer_type_node), 3,
XEXP (x, 0), Pmode, XEXP (y, 0), Pmode,
- size, Pmode);
+ convert_to_mode (TYPE_MODE (sizetype), size,
+ TREE_UNSIGNED (sizetype)),
+ TYPE_MODE (sizetype));
#else
emit_library_call (bcmp_libfunc, 0,
TYPE_MODE (integer_type_node), 3,
XEXP (x, 0), Pmode, XEXP (y, 0), Pmode,
- size, Pmode);
+ convert_to_mode (TYPE_MODE (integer_type_node),
+ size,
+ TREE_UNSIGNED (integer_type_node)),
+ TYPE_MODE (integer_type_node));
#endif
- emit_cmp_insn (hard_libcall_value (TYPE_MODE (integer_type_node)),
+
+ /* Immediately move the result of the libcall into a pseudo
+ register so reload doesn't clobber the value if it needs
+ the return register for a spill reg. */
+ result = gen_reg_rtx (TYPE_MODE (integer_type_node));
+ emit_move_insn (result,
+ hard_libcall_value (TYPE_MODE (integer_type_node)));
+ emit_cmp_insn (result,
const0_rtx, comparison, NULL_RTX,
TYPE_MODE (integer_type_node), 0, 0);
}
&& class != MODE_FLOAT)
{
rtx libfunc = cmp_optab->handlers[(int) mode].libfunc;
+ rtx result;
+
/* If we want unsigned, and this mode has a distinct unsigned
comparison routine, use that. */
if (unsignedp && ucmp_optab->handlers[(int) mode].libfunc)
emit_library_call (libfunc, 1,
word_mode, 2, x, mode, y, mode);
+ /* Immediately move the result of the libcall into a pseudo
+ register so reload doesn't clobber the value if it needs
+ the return register for a spill reg. */
+ result = gen_reg_rtx (word_mode);
+ emit_move_insn (result, hard_libcall_value (word_mode));
+
/* Integer comparison returns a result that must be compared against 1,
so that even if we do an unsigned compare afterward,
there is still a value that can represent the result "less than". */
-
- emit_cmp_insn (hard_libcall_value (word_mode), const1_rtx,
+ emit_cmp_insn (result, const1_rtx,
comparison, NULL_RTX, word_mode, unsignedp, 0);
return;
}
{
enum machine_mode mode = GET_MODE (x);
rtx libfunc = 0;
+ rtx result;
if (mode == HFmode)
switch (comparison)
emit_library_call (libfunc, 1,
word_mode, 2, x, mode, y, mode);
- emit_cmp_insn (hard_libcall_value (word_mode), const0_rtx, comparison,
+ /* Immediately move the result of the libcall into a pseudo
+ register so reload doesn't clobber the value if it needs
+ the return register for a spill reg. */
+ result = gen_reg_rtx (word_mode);
+ emit_move_insn (result, hard_libcall_value (word_mode));
+
+ emit_cmp_insn (result, const0_rtx, comparison,
NULL_RTX, word_mode, 0, 0);
}
\f
/* There is no such mode. Pretend the target is wide enough. */
fmode = GET_MODE (to);
- /* Avoid double-rounding when TO is narrower than FROM. */
+ /* Avoid double-rounding when TO is narrower than FROM. */
if ((significand_size (fmode) + 1)
< GET_MODE_BITSIZE (GET_MODE (from)))
{
/* The sign bit is not set. Convert as signed. */
expand_float (target, from, 0);
emit_jump_insn (gen_jump (label));
+ emit_barrier ();
/* The sign bit is set.
Convert to a usable (positive signed) value by shifting right
GET_MODE (to), from));
}
- if (GET_MODE (to) == GET_MODE (target))
- emit_move_insn (to, target);
- else
- convert_move (to, target, 0);
+ if (target != to)
+ {
+ if (GET_MODE (to) == GET_MODE (target))
+ emit_move_insn (to, target);
+ else
+ convert_move (to, target, 0);
+ }
}
\f
static optab
for (i = 0; i < NUM_MACHINE_MODES; i++)
{
movstr_optab[i] = CODE_FOR_nothing;
+ clrstr_optab[i] = CODE_FOR_nothing;
#ifdef HAVE_SECONDARY_RELOADS
reload_in_optab[i] = reload_out_optab[i] = CODE_FOR_nothing;
memset_libfunc = gen_rtx (SYMBOL_REF, Pmode, "memset");
bzero_libfunc = gen_rtx (SYMBOL_REF, Pmode, "bzero");
+ throw_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__throw");
+
eqhf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqhf2");
nehf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__nehf2");
gthf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gthf2");
\f
#ifdef BROKEN_LDEXP
-/* SCO 3.2 apparently has a broken ldexp. */
+/* SCO 3.2 apparently has a broken ldexp. */
double
ldexp(x,n)