mips.h (UNITS_PER_HWFPVALUE): Renamed from...
* config/mips/mips.h (UNITS_PER_HWFPVALUE): Renamed from... (UNITS_PER_FPVALUE): Defined as the width of a long double, or zero if no hardware floating point. (LONG_DUBLE_TYPE_SIZE): Set to 128 on N32 and N64. (MAX_FIXED_MODE_SIZE): Define to LONG_DOUBLE_TYPE_SIZE. (LIBGCC2_LONG_DOUBLE_TYPE_SIZE): Define. (BIGGEST_ALIGNMENT): Same as LONG_DOUBLE_TYPE_SIZE. (FUNCTION_VALUE_REGNO_P): Set for FP_RETURN+2 on N32 and N64. * config/mips/mips.c (mips_arg_info): Pass TFmode values in even FP registers on N32 and N64. (mips_setup_incoming_varargs): Use UNITS_PER_HWFPVALUE. (mips_va_start): Adjust alignment of ARG_POINTER_REGNUM. (mips_va_arg): Use UNITS_PER_HWFPVALUE. Impose additional even-register-like alignment to 128-bit arguments. (save_restore_insns): Use UNITS_PER_HWFPVALUE. (mips_function_value): Likewise. Return TFmode in $f0 and $f2 on N32 or N64. * config/mips/_tilib.c (__negti2, __ashlti3, __lshrti3): New. * config/mips/t-iris6 (LIB2FUNCS_EXTRA): Add _tilib.c. (TPBIT): Set to tp-bit.c. (tp-bit.c): Create out of fp-bit.c. From-SVN: r61945
This commit is contained in:
parent
2956f353ba
commit
8a3812735f
|
@ -1,3 +1,27 @@
|
|||
2003-01-28 Alexandre Oliva <aoliva@redhat.com>
|
||||
|
||||
* config/mips/mips.h (UNITS_PER_HWFPVALUE): Renamed from...
|
||||
(UNITS_PER_FPVALUE): Defined as the width of a long double, or
|
||||
zero if no hardware floating point.
|
||||
(LONG_DUBLE_TYPE_SIZE): Set to 128 on N32 and N64.
|
||||
(MAX_FIXED_MODE_SIZE): Define to LONG_DOUBLE_TYPE_SIZE.
|
||||
(LIBGCC2_LONG_DOUBLE_TYPE_SIZE): Define.
|
||||
(BIGGEST_ALIGNMENT): Same as LONG_DOUBLE_TYPE_SIZE.
|
||||
(FUNCTION_VALUE_REGNO_P): Set for FP_RETURN+2 on N32 and N64.
|
||||
* config/mips/mips.c (mips_arg_info): Pass TFmode values in
|
||||
even FP registers on N32 and N64.
|
||||
(mips_setup_incoming_varargs): Use UNITS_PER_HWFPVALUE.
|
||||
(mips_va_start): Adjust alignment of ARG_POINTER_REGNUM.
|
||||
(mips_va_arg): Use UNITS_PER_HWFPVALUE. Impose additional
|
||||
even-register-like alignment to 128-bit arguments.
|
||||
(save_restore_insns): Use UNITS_PER_HWFPVALUE.
|
||||
(mips_function_value): Likewise. Return TFmode in $f0 and $f2
|
||||
on N32 or N64.
|
||||
* config/mips/_tilib.c (__negti2, __ashlti3, __lshrti3): New.
|
||||
* config/mips/t-iris6 (LIB2FUNCS_EXTRA): Add _tilib.c.
|
||||
(TPBIT): Set to tp-bit.c.
|
||||
(tp-bit.c): Create out of fp-bit.c.
|
||||
|
||||
2003-01-28 Gabriel Dos Reis <gdr@integrable-solutions.net>
|
||||
|
||||
* c-parse.in: Remove '%expect 32' directive in objc mode.
|
||||
|
|
|
@ -4315,9 +4315,11 @@ mips_arg_info (cum, mode, type, named, info)
|
|||
is a double, but $f14 if it is a single. Otherwise, on a
|
||||
32-bit double-float machine, each FP argument must start in a
|
||||
new register pair. */
|
||||
even_reg_p = ((mips_abi == ABI_O64 && mode == SFmode) || FP_INC > 1);
|
||||
even_reg_p = (GET_MODE_SIZE (mode) > UNITS_PER_HWFPVALUE
|
||||
|| (mips_abi == ABI_O64 && mode == SFmode)
|
||||
|| FP_INC > 1);
|
||||
}
|
||||
else if (!TARGET_64BIT)
|
||||
else if (!TARGET_64BIT || LONG_DOUBLE_TYPE_SIZE == 128)
|
||||
{
|
||||
if (GET_MODE_CLASS (mode) == MODE_INT
|
||||
|| GET_MODE_CLASS (mode) == MODE_FLOAT)
|
||||
|
@ -4629,7 +4631,7 @@ mips_setup_incoming_varargs (cum, mode, type, no_rtl)
|
|||
rtx ptr = plus_constant (virtual_incoming_args_rtx, off);
|
||||
emit_move_insn (gen_rtx_MEM (mode, ptr),
|
||||
gen_rtx_REG (mode, FP_ARG_FIRST + i));
|
||||
off += UNITS_PER_FPVALUE;
|
||||
off += UNITS_PER_HWFPVALUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4706,6 +4708,15 @@ mips_va_start (valist, nextarg)
|
|||
{
|
||||
const CUMULATIVE_ARGS *cum = ¤t_function_args_info;
|
||||
|
||||
/* ARG_POINTER_REGNUM is initialized to STACK_POINTER_BOUNDARY, but
|
||||
since the stack is aligned for a pair of argument-passing slots,
|
||||
and the beginning of a variable argument list may be an odd slot,
|
||||
we have to decrease its alignment. */
|
||||
if (cfun && cfun->emit->regno_pointer_align)
|
||||
while (((current_function_pretend_args_size * BITS_PER_UNIT)
|
||||
& (REGNO_POINTER_ALIGN (ARG_POINTER_REGNUM) - 1)) != 0)
|
||||
REGNO_POINTER_ALIGN (ARG_POINTER_REGNUM) /= 2;
|
||||
|
||||
if (mips_abi == ABI_EABI)
|
||||
{
|
||||
int gpr_save_area_size;
|
||||
|
@ -4903,9 +4914,9 @@ mips_va_arg (valist, type)
|
|||
off = build (COMPONENT_REF, TREE_TYPE (f_foff), valist, f_foff);
|
||||
|
||||
/* When floating-point registers are saved to the stack,
|
||||
each one will take up UNITS_PER_FPVALUE bytes, regardless
|
||||
each one will take up UNITS_PER_HWFPVALUE bytes, regardless
|
||||
of the float's precision. */
|
||||
rsize = UNITS_PER_FPVALUE;
|
||||
rsize = UNITS_PER_HWFPVALUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -4924,7 +4935,7 @@ mips_va_arg (valist, type)
|
|||
bytes (= PARM_BOUNDARY bits). RSIZE can sometimes be smaller
|
||||
than that, such as in the combination -mgp64 -msingle-float
|
||||
-fshort-double. Doubles passed in registers will then take
|
||||
up UNITS_PER_FPVALUE bytes, but those passed on the stack
|
||||
up UNITS_PER_HWFPVALUE bytes, but those passed on the stack
|
||||
take up UNITS_PER_WORD bytes. */
|
||||
osize = MAX (rsize, UNITS_PER_WORD);
|
||||
|
||||
|
@ -4998,7 +5009,10 @@ mips_va_arg (valist, type)
|
|||
that alignments <= UNITS_PER_WORD are preserved by the va_arg
|
||||
increment mechanism. */
|
||||
|
||||
if (TARGET_64BIT)
|
||||
if ((mips_abi == ABI_N32 || mips_abi == ABI_64)
|
||||
&& TYPE_ALIGN (type) > 64)
|
||||
align = 16;
|
||||
else if (TARGET_64BIT)
|
||||
align = 8;
|
||||
else if (TYPE_ALIGN (type) > 32)
|
||||
align = 8;
|
||||
|
@ -7080,7 +7094,7 @@ save_restore_insns (store_p, large_reg, large_offset)
|
|||
/* Pick which pointer to use as a base register. */
|
||||
fp_offset = cfun->machine->frame.fp_sp_offset;
|
||||
end_offset = fp_offset - (cfun->machine->frame.fp_reg_size
|
||||
- UNITS_PER_FPVALUE);
|
||||
- UNITS_PER_HWFPVALUE);
|
||||
|
||||
if (fp_offset < 0 || end_offset < 0)
|
||||
internal_error
|
||||
|
@ -7133,7 +7147,7 @@ save_restore_insns (store_p, large_reg, large_offset)
|
|||
else
|
||||
emit_move_insn (reg_rtx, mem_rtx);
|
||||
|
||||
fp_offset -= UNITS_PER_FPVALUE;
|
||||
fp_offset -= UNITS_PER_HWFPVALUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8264,11 +8278,26 @@ mips_function_value (valtype, func, mode)
|
|||
}
|
||||
mclass = GET_MODE_CLASS (mode);
|
||||
|
||||
if (mclass == MODE_FLOAT && GET_MODE_SIZE (mode) <= UNITS_PER_FPVALUE)
|
||||
if (mclass == MODE_FLOAT && GET_MODE_SIZE (mode) <= UNITS_PER_HWFPVALUE)
|
||||
reg = FP_RETURN;
|
||||
|
||||
else if (mclass == MODE_FLOAT && mode == TFmode)
|
||||
/* long doubles are really split between f0 and f2, not f1. Eek.
|
||||
Use DImode for each component, since GCC wants integer modes
|
||||
for subregs. */
|
||||
return gen_rtx_PARALLEL
|
||||
(VOIDmode,
|
||||
gen_rtvec (2,
|
||||
gen_rtx_EXPR_LIST (VOIDmode,
|
||||
gen_rtx_REG (DImode, FP_RETURN),
|
||||
GEN_INT (0)),
|
||||
gen_rtx_EXPR_LIST (VOIDmode,
|
||||
gen_rtx_REG (DImode, FP_RETURN + 2),
|
||||
GEN_INT (GET_MODE_SIZE (mode) / 2))));
|
||||
|
||||
|
||||
else if (mclass == MODE_COMPLEX_FLOAT
|
||||
&& GET_MODE_SIZE (mode) <= UNITS_PER_FPVALUE * 2)
|
||||
&& GET_MODE_SIZE (mode) <= UNITS_PER_HWFPVALUE * 2)
|
||||
{
|
||||
enum machine_mode cmode = GET_MODE_INNER (mode);
|
||||
|
||||
|
|
|
@ -1517,8 +1517,14 @@ do { \
|
|||
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 (TARGET_SOFT_FLOAT ? 0 : FP_INC * UNITS_PER_FPREG)
|
||||
/* The largest size of value that can be held in floating-point
|
||||
registers and moved with a single instruction. */
|
||||
#define UNITS_PER_HWFPVALUE (TARGET_SOFT_FLOAT ? 0 : FP_INC * UNITS_PER_FPREG)
|
||||
|
||||
/* The largest size of value that can be held in floating-point
|
||||
registers. */
|
||||
#define UNITS_PER_FPVALUE \
|
||||
(TARGET_SOFT_FLOAT ? 0 : (LONG_DOUBLE_TYPE_SIZE / BITS_PER_UNIT))
|
||||
|
||||
/* The number of bytes in a double. */
|
||||
#define UNITS_PER_DOUBLE (TYPE_PRECISION (double_type_node) / BITS_PER_UNIT)
|
||||
|
@ -1565,7 +1571,21 @@ do { \
|
|||
/* A C expression for the size in bits of the type `long double' on
|
||||
the target machine. If you don't define this, the default is two
|
||||
words. */
|
||||
#define LONG_DOUBLE_TYPE_SIZE 64
|
||||
#define LONG_DOUBLE_TYPE_SIZE \
|
||||
(mips_abi == ABI_N32 || mips_abi == ABI_64 ? 128 : 64)
|
||||
|
||||
/* long double is not a fixed mode, but the idea is that, if we
|
||||
support long double, we also want a 128-bit integer type. */
|
||||
#define MAX_FIXED_MODE_SIZE LONG_DOUBLE_TYPE_SIZE
|
||||
|
||||
#ifdef IN_LIBGCC2
|
||||
#if (defined _ABIN32 && _MIPS_SIM == _ABIN32) \
|
||||
|| (defined _ABI64 && _MIPS_SIM == _ABI64)
|
||||
# define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 128
|
||||
# else
|
||||
# define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 64
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Width in bits of a pointer.
|
||||
See also the macro `Pmode' defined below. */
|
||||
|
@ -1592,7 +1612,7 @@ do { \
|
|||
#define STRUCTURE_SIZE_BOUNDARY 8
|
||||
|
||||
/* There is no point aligning anything to a rounder boundary than this. */
|
||||
#define BIGGEST_ALIGNMENT 64
|
||||
#define BIGGEST_ALIGNMENT LONG_DOUBLE_TYPE_SIZE
|
||||
|
||||
/* Set this nonzero if move instructions will actually fail to work
|
||||
when given unaligned data. */
|
||||
|
@ -2654,7 +2674,9 @@ extern enum reg_class mips_char_to_class[256];
|
|||
On the MIPS, R2 R3 and F0 F2 are the only register thus used.
|
||||
Currently, R2 and F0 are only implemented here (C has no complex type) */
|
||||
|
||||
#define FUNCTION_VALUE_REGNO_P(N) ((N) == GP_RETURN || (N) == FP_RETURN)
|
||||
#define FUNCTION_VALUE_REGNO_P(N) ((N) == GP_RETURN || (N) == FP_RETURN \
|
||||
|| (LONG_DOUBLE_TYPE_SIZE == 128 && FP_RETURN != GP_RETURN \
|
||||
&& (N) == FP_RETURN + 2))
|
||||
|
||||
/* 1 if N is a possible register number for function argument passing.
|
||||
We have no FP argument registers when soft-float. When FP registers
|
||||
|
|
|
@ -18,3 +18,16 @@ CRTSTUFF_T_CFLAGS=-g1
|
|||
# This is only needed in the static libgcc as a band-aid until gcc correctly
|
||||
# implements the N32/N64 ABI structure passing conventions
|
||||
LIB2FUNCS_STATIC_EXTRA = $(srcdir)/config/mips/irix6-libc-compat.c
|
||||
|
||||
LIB2FUNCS_EXTRA = $(srcdir)/config/mips/_tilib.c
|
||||
|
||||
TPBIT = tp-bit.c
|
||||
|
||||
tp-bit.c: $(srcdir)/config/fp-bit.c
|
||||
echo '#ifdef __MIPSEL__' > tp-bit.c
|
||||
echo '# define FLOAT_BIT_ORDER_MISMATCH' >> tp-bit.c
|
||||
echo '#endif' >> tp-bit.c
|
||||
echo '#if __LDBL_MANT_DIG__ == 106' >> tp-bit.c
|
||||
echo '# define TFLOAT' >> tp-bit.c
|
||||
cat $(srcdir)/config/fp-bit.c >> tp-bit.c
|
||||
echo '#endif' >> tp-bit.c
|
||||
|
|
Loading…
Reference in New Issue