mips.h (FP_INC, [...]): New macros.
* config/mips/mips.h (FP_INC, UNITS_PER_FPVALUE): New macros. * config/mips/mips.c (compute_frame_size): Retrofit them here. (save_restore_insns, mips_expand_epilogue): And here. (build_mips16_call_stub): And here. (mips_function_value): Use the new macros to decide whether a single or complex float can be returned in floating-point registers. Return a parallel rtx in the complex case. From-SVN: r50766
This commit is contained in:
parent
1e3881c2a0
commit
3f26edaa19
|
@ -1,3 +1,13 @@
|
||||||
|
2002-03-14 Richard Sandiford <rsandifo@redhat.com>
|
||||||
|
|
||||||
|
* config/mips/mips.h (FP_INC, UNITS_PER_FPVALUE): New macros.
|
||||||
|
* config/mips/mips.c (compute_frame_size): Retrofit them here.
|
||||||
|
(save_restore_insns, mips_expand_epilogue): And here.
|
||||||
|
(build_mips16_call_stub): And here.
|
||||||
|
(mips_function_value): Use the new macros to decide whether a single
|
||||||
|
or complex float can be returned in floating-point registers. Return
|
||||||
|
a parallel rtx in the complex case.
|
||||||
|
|
||||||
Thu Mar 14 11:03:12 CET 2002 Jan Hubicka <jh@suse.cz>
|
Thu Mar 14 11:03:12 CET 2002 Jan Hubicka <jh@suse.cz>
|
||||||
|
|
||||||
* toplev.c (rest_of_compilation): Add CLEANUP_UPDATE_LIFE to cfg_cleanup
|
* toplev.c (rest_of_compilation): Add CLEANUP_UPDATE_LIFE to cfg_cleanup
|
||||||
|
|
|
@ -6362,6 +6362,7 @@ compute_frame_size (size)
|
||||||
long fmask; /* mask of saved fp registers */
|
long fmask; /* mask of saved fp registers */
|
||||||
int fp_inc; /* 1 or 2 depending on the size of fp regs */
|
int fp_inc; /* 1 or 2 depending on the size of fp regs */
|
||||||
long fp_bits; /* bitmask to use for each fp register */
|
long fp_bits; /* bitmask to use for each fp register */
|
||||||
|
tree return_type;
|
||||||
|
|
||||||
gp_reg_size = 0;
|
gp_reg_size = 0;
|
||||||
fp_reg_size = 0;
|
fp_reg_size = 0;
|
||||||
|
@ -6380,6 +6381,7 @@ compute_frame_size (size)
|
||||||
args_size = 4 * UNITS_PER_WORD;
|
args_size = 4 * UNITS_PER_WORD;
|
||||||
|
|
||||||
total_size = var_size + args_size + extra_size;
|
total_size = var_size + args_size + extra_size;
|
||||||
|
return_type = DECL_RESULT (current_function_decl);
|
||||||
|
|
||||||
/* Calculate space needed for gp registers. */
|
/* Calculate space needed for gp registers. */
|
||||||
for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++)
|
for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++)
|
||||||
|
@ -6398,12 +6400,9 @@ compute_frame_size (size)
|
||||||
&& regno == GP_REG_FIRST + 31
|
&& regno == GP_REG_FIRST + 31
|
||||||
&& mips16_hard_float
|
&& mips16_hard_float
|
||||||
&& ! mips_entry
|
&& ! mips_entry
|
||||||
&& ! aggregate_value_p (DECL_RESULT (current_function_decl))
|
&& ! aggregate_value_p (return_type)
|
||||||
&& (GET_MODE_CLASS (DECL_MODE (DECL_RESULT (current_function_decl)))
|
&& GET_MODE_CLASS (DECL_MODE (return_type)) == MODE_FLOAT
|
||||||
== MODE_FLOAT)
|
&& GET_MODE_SIZE (DECL_MODE (return_type)) <= UNITS_PER_FPVALUE))
|
||||||
&& (! TARGET_SINGLE_FLOAT
|
|
||||||
|| (GET_MODE_SIZE (DECL_MODE (DECL_RESULT (current_function_decl)))
|
|
||||||
<= 4))))
|
|
||||||
{
|
{
|
||||||
gp_reg_size += GET_MODE_SIZE (gpr_mode);
|
gp_reg_size += GET_MODE_SIZE (gpr_mode);
|
||||||
mask |= 1L << (regno - GP_REG_FIRST);
|
mask |= 1L << (regno - GP_REG_FIRST);
|
||||||
|
@ -6854,12 +6853,10 @@ save_restore_insns (store_p, large_reg, large_offset, file)
|
||||||
/* Save floating point registers if needed. */
|
/* Save floating point registers if needed. */
|
||||||
if (fmask)
|
if (fmask)
|
||||||
{
|
{
|
||||||
int fp_inc = (TARGET_FLOAT64 || TARGET_SINGLE_FLOAT) ? 1 : 2;
|
|
||||||
int fp_size = fp_inc * UNITS_PER_FPREG;
|
|
||||||
|
|
||||||
/* Pick which pointer to use as a base register. */
|
/* Pick which pointer to use as a base register. */
|
||||||
fp_offset = current_frame_info.fp_sp_offset;
|
fp_offset = current_frame_info.fp_sp_offset;
|
||||||
end_offset = fp_offset - (current_frame_info.fp_reg_size - fp_size);
|
end_offset = fp_offset - (current_frame_info.fp_reg_size
|
||||||
|
- UNITS_PER_FPVALUE);
|
||||||
|
|
||||||
if (fp_offset < 0 || end_offset < 0)
|
if (fp_offset < 0 || end_offset < 0)
|
||||||
internal_error
|
internal_error
|
||||||
|
@ -6905,9 +6902,9 @@ save_restore_insns (store_p, large_reg, large_offset, file)
|
||||||
|
|
||||||
/* This loop must iterate over the same space as its companion in
|
/* This loop must iterate over the same space as its companion in
|
||||||
compute_frame_size. */
|
compute_frame_size. */
|
||||||
for (regno = (FP_REG_LAST - fp_inc + 1);
|
for (regno = (FP_REG_LAST - FP_INC + 1);
|
||||||
regno >= FP_REG_FIRST;
|
regno >= FP_REG_FIRST;
|
||||||
regno -= fp_inc)
|
regno -= FP_INC)
|
||||||
if (BITSET_P (fmask, regno - FP_REG_FIRST))
|
if (BITSET_P (fmask, regno - FP_REG_FIRST))
|
||||||
{
|
{
|
||||||
if (file == 0)
|
if (file == 0)
|
||||||
|
@ -6939,7 +6936,7 @@ save_restore_insns (store_p, large_reg, large_offset, file)
|
||||||
fprintf (file, "(%s)\n", reg_names[REGNO(base_reg_rtx)]);
|
fprintf (file, "(%s)\n", reg_names[REGNO(base_reg_rtx)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
fp_offset -= fp_size;
|
fp_offset -= UNITS_PER_FPVALUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7769,23 +7766,24 @@ mips_expand_epilogue ()
|
||||||
int
|
int
|
||||||
mips_can_use_return_insn ()
|
mips_can_use_return_insn ()
|
||||||
{
|
{
|
||||||
|
tree return_type;
|
||||||
|
|
||||||
if (! reload_completed)
|
if (! reload_completed)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (regs_ever_live[31] || current_function_profile)
|
if (regs_ever_live[31] || current_function_profile)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
return_type = DECL_RESULT (current_function_decl);
|
||||||
|
|
||||||
/* In mips16 mode, a function which returns a floating point value
|
/* In mips16 mode, a function which returns a floating point value
|
||||||
needs to arrange to copy the return value into the floating point
|
needs to arrange to copy the return value into the floating point
|
||||||
registers. */
|
registers. */
|
||||||
if (TARGET_MIPS16
|
if (TARGET_MIPS16
|
||||||
&& mips16_hard_float
|
&& mips16_hard_float
|
||||||
&& ! aggregate_value_p (DECL_RESULT (current_function_decl))
|
&& ! aggregate_value_p (return_type)
|
||||||
&& (GET_MODE_CLASS (DECL_MODE (DECL_RESULT (current_function_decl)))
|
&& GET_MODE_CLASS (DECL_MODE (return_type)) == MODE_FLOAT
|
||||||
== MODE_FLOAT)
|
&& GET_MODE_SIZE (DECL_MODE (return_type)) <= UNITS_PER_FPVALUE)
|
||||||
&& (! TARGET_SINGLE_FLOAT
|
|
||||||
|| (GET_MODE_SIZE (DECL_MODE (DECL_RESULT (current_function_decl)))
|
|
||||||
<= 4)))
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (current_frame_info.initialized)
|
if (current_frame_info.initialized)
|
||||||
|
@ -7951,41 +7949,23 @@ mips_function_value (valtype, func)
|
||||||
just as PROMOTE_MODE does. */
|
just as PROMOTE_MODE does. */
|
||||||
mode = promote_mode (valtype, mode, &unsignedp, 1);
|
mode = promote_mode (valtype, mode, &unsignedp, 1);
|
||||||
|
|
||||||
if (mclass == MODE_FLOAT)
|
if (mclass == MODE_FLOAT && GET_MODE_SIZE (mode) <= UNITS_PER_FPVALUE)
|
||||||
|
reg = FP_RETURN;
|
||||||
|
|
||||||
|
else if (mclass == MODE_COMPLEX_FLOAT
|
||||||
|
&& GET_MODE_SIZE (mode) <= UNITS_PER_FPVALUE * 2)
|
||||||
{
|
{
|
||||||
if (TARGET_SINGLE_FLOAT
|
enum machine_mode cmode = TYPE_MODE (TREE_TYPE (valtype));
|
||||||
&& (mclass == MODE_FLOAT
|
|
||||||
? GET_MODE_SIZE (mode) > 4 : GET_MODE_SIZE (mode) / 2 > 4))
|
|
||||||
reg = GP_RETURN;
|
|
||||||
else
|
|
||||||
reg = FP_RETURN;
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (mclass == MODE_COMPLEX_FLOAT)
|
return gen_rtx_PARALLEL
|
||||||
{
|
(VOIDmode,
|
||||||
if (TARGET_FLOAT64)
|
gen_rtvec (2,
|
||||||
reg = FP_RETURN;
|
gen_rtx_EXPR_LIST (VOIDmode,
|
||||||
else if (mode == SCmode)
|
gen_rtx_REG (cmode, FP_RETURN),
|
||||||
{
|
GEN_INT (0)),
|
||||||
/* When FP registers are 32 bits, we can't directly reference
|
gen_rtx_EXPR_LIST (VOIDmode,
|
||||||
the odd numbered ones, so let's make a pair of evens. */
|
gen_rtx_REG (cmode, FP_RETURN + FP_INC),
|
||||||
|
GEN_INT (GET_MODE_SIZE (cmode)))));
|
||||||
enum machine_mode cmode = TYPE_MODE (TREE_TYPE (valtype));
|
|
||||||
|
|
||||||
return gen_rtx_PARALLEL
|
|
||||||
(VOIDmode,
|
|
||||||
gen_rtvec (2,
|
|
||||||
gen_rtx_EXPR_LIST (VOIDmode,
|
|
||||||
gen_rtx_REG (cmode,
|
|
||||||
FP_RETURN),
|
|
||||||
GEN_INT (0)),
|
|
||||||
gen_rtx_EXPR_LIST (VOIDmode,
|
|
||||||
gen_rtx_REG (cmode,
|
|
||||||
FP_RETURN + 2),
|
|
||||||
GEN_INT (4))));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
reg = FP_RETURN;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (TREE_CODE (valtype) == RECORD_TYPE
|
else if (TREE_CODE (valtype) == RECORD_TYPE
|
||||||
|
@ -8680,8 +8660,7 @@ build_mips16_call_stub (retval, fnmem, arg_size, fp_code)
|
||||||
register. */
|
register. */
|
||||||
fpret = (retval != 0
|
fpret = (retval != 0
|
||||||
&& GET_MODE_CLASS (GET_MODE (retval)) == MODE_FLOAT
|
&& GET_MODE_CLASS (GET_MODE (retval)) == MODE_FLOAT
|
||||||
&& (! TARGET_SINGLE_FLOAT
|
&& GET_MODE_SIZE (GET_MODE (retval)) <= UNITS_PER_FPVALUE);
|
||||||
|| GET_MODE_SIZE (GET_MODE (retval)) <= 4));
|
|
||||||
|
|
||||||
/* We don't need to do anything if there were no floating point
|
/* We don't need to do anything if there were no floating point
|
||||||
arguments and the value will not be returned in a floating point
|
arguments and the value will not be returned in a floating point
|
||||||
|
|
|
@ -1591,6 +1591,13 @@ do { \
|
||||||
/* For MIPS, width of a floating point register. */
|
/* For MIPS, width of a floating point register. */
|
||||||
#define UNITS_PER_FPREG (TARGET_FLOAT64 ? 8 : 4)
|
#define UNITS_PER_FPREG (TARGET_FLOAT64 ? 8 : 4)
|
||||||
|
|
||||||
|
/* If register $f0 holds a floating-point value, $f(0 + FP_INC) is
|
||||||
|
the next available register. */
|
||||||
|
#define FP_INC (TARGET_FLOAT64 || TARGET_SINGLE_FLOAT ? 1 : 2)
|
||||||
|
|
||||||
|
/* The largest size of value that can be held in floating-point registers. */
|
||||||
|
#define UNITS_PER_FPVALUE (FP_INC * UNITS_PER_FPREG)
|
||||||
|
|
||||||
/* A C expression for the size in bits of the type `int' on the
|
/* A C expression for the size in bits of the type `int' on the
|
||||||
target machine. If you don't define this, the default is one
|
target machine. If you don't define this, the default is one
|
||||||
word. */
|
word. */
|
||||||
|
|
Loading…
Reference in New Issue