diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 18a6965e4ec..d0753beaa78 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2007-05-08 Sandra Loosemore + Nigel Stephens + + * config/mips/mips.h (MAX_FPRS_PER_FMT): Renamed from FP_INC. + Update comments and all uses. + (MIN_FPRS_PER_FMT): Define. + * config/mips/mips.c (function_arg): Fix to correctly handle + the -mips32r2 -mfp64 -mabi=32 case. + (override_options): Enable use of odd-numbered registers for + SFmode values on MIPS32. + (mips_save_reg_p): Save whole floating-point register pair if + either half is used. + (compute_frame_size): Fix comment. + 2007-05-08 Jie Zhang * config/bfin/bfin-protos.h (bfin_expand_epilogue): Add a third diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 55bacf7bb19..a719a1020dd 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -3528,7 +3528,7 @@ mips_emit_fcc_reload (rtx dest, rtx src, rtx scratch) src = gen_rtx_REG (SFmode, true_regnum (src)); fp1 = gen_rtx_REG (SFmode, REGNO (scratch)); - fp2 = gen_rtx_REG (SFmode, REGNO (scratch) + FP_INC); + fp2 = gen_rtx_REG (SFmode, REGNO (scratch) + MAX_FPRS_PER_FMT); emit_move_insn (copy_rtx (fp1), src); emit_move_insn (copy_rtx (fp2), CONST0_RTX (SFmode)); @@ -3872,7 +3872,7 @@ function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, if (mips_abi != ABI_EABI || !info.fpr_p) cum->num_gprs = info.reg_offset + info.reg_words; else if (info.reg_words > 0) - cum->num_fprs += FP_INC; + cum->num_fprs += MAX_FPRS_PER_FMT; if (info.stack_words > 0) cum->stack_words = info.stack_offset + info.stack_words; @@ -4006,10 +4006,11 @@ function_arg (const CUMULATIVE_ARGS *cum, enum machine_mode mode, if (!info.fpr_p) return gen_rtx_REG (mode, GP_ARG_FIRST + info.reg_offset); - else if (info.reg_offset == 1) - /* This code handles the special o32 case in which the second word - of the argument structure is passed in floating-point registers. */ - return gen_rtx_REG (mode, FP_ARG_FIRST + FP_INC); + else if (mips_abi == ABI_32 && TARGET_DOUBLE_FLOAT && info.reg_offset > 0) + /* In o32, the second argument is always passed in $f14 + for TARGET_DOUBLE_FLOAT, regardless of whether the + first argument was a word or doubleword. */ + return gen_rtx_REG (mode, FP_ARG_FIRST + 2); else return gen_rtx_REG (mode, FP_ARG_FIRST + info.reg_offset); } @@ -4150,7 +4151,8 @@ mips_setup_incoming_varargs (CUMULATIVE_ARGS *cum, enum machine_mode mode, mode = TARGET_SINGLE_FLOAT ? SFmode : DFmode; - for (i = local_cum.num_fprs; i < MAX_ARGS_IN_REGISTERS; i += FP_INC) + for (i = local_cum.num_fprs; i < MAX_ARGS_IN_REGISTERS; + i += MAX_FPRS_PER_FMT) { rtx ptr, mem; @@ -5098,7 +5100,9 @@ override_options (void) temp = ((regno & 1) == 0 || size <= UNITS_PER_WORD); else if (FP_REG_P (regno)) - temp = ((regno % FP_INC) == 0) + temp = ((((regno % MAX_FPRS_PER_FMT) == 0) + || (MIN_FPRS_PER_FMT == 1 + && size <= UNITS_PER_FPREG)) && (((class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT || class == MODE_VECTOR_FLOAT) && size <= UNITS_PER_FPVALUE) @@ -5112,7 +5116,7 @@ override_options (void) && size >= MIN_UNITS_PER_WORD && size <= UNITS_PER_FPREG) /* Allow TFmode for CCmode reloads. */ - || (ISA_HAS_8CC && mode == TFmode)); + || (ISA_HAS_8CC && mode == TFmode))); else if (ACC_REG_P (regno)) temp = (INTEGRAL_MODE_P (mode) @@ -6285,6 +6289,15 @@ mips_save_reg_p (unsigned int regno) if (regs_ever_live[regno] && !call_used_regs[regno]) return true; + /* Save both registers in an FPR pair if either one is used. This is + needed for the case when MIN_FPRS_PER_FMT == 1, which allows the odd + register to be used without the even register. */ + if (FP_REG_P (regno) + && MAX_FPRS_PER_FMT == 2 + && regs_ever_live[regno + 1] + && !call_used_regs[regno + 1]) + return true; + /* We need to save the old frame pointer before setting up a new one. */ if (regno == HARD_FRAME_POINTER_REGNUM && frame_pointer_needed) return true; @@ -6437,15 +6450,15 @@ compute_frame_size (HOST_WIDE_INT size) } /* This loop must iterate over the same space as its companion in - save_restore_insns. */ - for (regno = (FP_REG_LAST - FP_INC + 1); + mips_for_each_saved_reg. */ + for (regno = (FP_REG_LAST - MAX_FPRS_PER_FMT + 1); regno >= FP_REG_FIRST; - regno -= FP_INC) + regno -= MAX_FPRS_PER_FMT) { if (mips_save_reg_p (regno)) { - fp_reg_size += FP_INC * UNITS_PER_FPREG; - fmask |= ((1 << FP_INC) - 1) << (regno - FP_REG_FIRST); + fp_reg_size += MAX_FPRS_PER_FMT * UNITS_PER_FPREG; + fmask |= ((1 << MAX_FPRS_PER_FMT) - 1) << (regno - FP_REG_FIRST); } } @@ -6467,7 +6480,8 @@ compute_frame_size (HOST_WIDE_INT size) cfun->machine->frame.fmask = fmask; cfun->machine->frame.initialized = reload_completed; cfun->machine->frame.num_gp = gp_reg_size / UNITS_PER_WORD; - cfun->machine->frame.num_fp = fp_reg_size / (FP_INC * UNITS_PER_FPREG); + cfun->machine->frame.num_fp = (fp_reg_size + / (MAX_FPRS_PER_FMT * UNITS_PER_FPREG)); if (mask) { @@ -6490,7 +6504,7 @@ compute_frame_size (HOST_WIDE_INT size) offset = (args_size + cprestore_size + var_size + gp_reg_rounded + fp_reg_size - - FP_INC * UNITS_PER_FPREG); + - MAX_FPRS_PER_FMT * UNITS_PER_FPREG); cfun->machine->frame.fp_sp_offset = offset; cfun->machine->frame.fp_save_offset = offset - total_size; } @@ -6593,9 +6607,9 @@ mips_for_each_saved_reg (HOST_WIDE_INT sp_offset, mips_save_restore_fn fn) compute_frame_size. */ offset = cfun->machine->frame.fp_sp_offset - sp_offset; fpr_mode = (TARGET_SINGLE_FLOAT ? SFmode : DFmode); - for (regno = (FP_REG_LAST - FP_INC + 1); + for (regno = (FP_REG_LAST - MAX_FPRS_PER_FMT + 1); regno >= FP_REG_FIRST; - regno -= FP_INC) + regno -= MAX_FPRS_PER_FMT) if (BITSET_P (cfun->machine->frame.fmask, regno - FP_REG_FIRST)) { mips_save_restore_reg (fpr_mode, regno, offset, fn); @@ -7507,7 +7521,7 @@ mips_return_fpr_pair (enum machine_mode mode, { int inc; - inc = (TARGET_NEWABI ? 2 : FP_INC); + inc = (TARGET_NEWABI ? 2 : MAX_FPRS_PER_FMT); return gen_rtx_PARALLEL (mode, gen_rtvec (2, @@ -7645,7 +7659,7 @@ mips_cannot_change_mode_class (enum machine_mode from, registers, the first register always holds the low word. We therefore can't allow FPRs to change between single-word and multi-word modes. */ - if (FP_INC > 1 && reg_classes_intersect_p (FP_REGS, class)) + if (MAX_FPRS_PER_FMT > 1 && reg_classes_intersect_p (FP_REGS, class)) return true; } else diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index e3c631e087e..fff2e660400 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -1021,13 +1021,19 @@ extern const struct mips_rtx_cost_data *mips_cost; /* For MIPS, width of a floating point register. */ #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 number of consecutive floating-point registers needed to store the + largest format supported by the FPU. */ +#define MAX_FPRS_PER_FMT (TARGET_FLOAT64 || TARGET_SINGLE_FLOAT ? 1 : 2) + +/* The number of consecutive floating-point registers needed to store the + smallest format supported by the FPU. */ +#define MIN_FPRS_PER_FMT \ + (ISA_MIPS32 || ISA_MIPS32R2 || ISA_MIPS64 ? 1 : MAX_FPRS_PER_FMT) /* 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) +#define UNITS_PER_HWFPVALUE \ + (TARGET_SOFT_FLOAT ? 0 : MAX_FPRS_PER_FMT * UNITS_PER_FPREG) /* The largest size of value that can be held in floating-point registers. */