diff options
Diffstat (limited to 'gcc/config/rs6000/rs6000.c')
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 65 |
1 files changed, 33 insertions, 32 deletions
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 1973476..8493e77 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -3199,24 +3199,26 @@ invalid_e500_subreg (rtx op, enum machine_mode mode) if (TARGET_E500_DOUBLE) { /* Reject (subreg:SI (reg:DF)); likewise with subreg:DI or - subreg:TI and reg:TF. */ + subreg:TI and reg:TF. Decimal float modes are like integer + modes (only low part of each register used) for this + purpose. */ if (GET_CODE (op) == SUBREG - && (mode == SImode || mode == DImode || mode == TImode) + && (mode == SImode || mode == DImode || mode == TImode + || mode == DDmode || mode == TDmode) && REG_P (SUBREG_REG (op)) && (GET_MODE (SUBREG_REG (op)) == DFmode - || GET_MODE (SUBREG_REG (op)) == TFmode - || GET_MODE (SUBREG_REG (op)) == DDmode - || GET_MODE (SUBREG_REG (op)) == TDmode)) + || GET_MODE (SUBREG_REG (op)) == TFmode)) return true; /* Reject (subreg:DF (reg:DI)); likewise with subreg:TF and reg:TI. */ if (GET_CODE (op) == SUBREG - && (mode == DFmode || mode == TFmode - || mode == DDmode || mode == TDmode) + && (mode == DFmode || mode == TFmode) && REG_P (SUBREG_REG (op)) && (GET_MODE (SUBREG_REG (op)) == DImode - || GET_MODE (SUBREG_REG (op)) == TImode)) + || GET_MODE (SUBREG_REG (op)) == TImode + || GET_MODE (SUBREG_REG (op)) == DDmode + || GET_MODE (SUBREG_REG (op)) == TDmode)) return true; } @@ -3467,10 +3469,10 @@ rs6000_legitimate_offset_address_p (enum machine_mode mode, rtx x, int strict) return SPE_CONST_OFFSET_OK (offset); case DFmode: - case DDmode: if (TARGET_E500_DOUBLE) return SPE_CONST_OFFSET_OK (offset); + case DDmode: case DImode: /* On e500v2, we may have: @@ -3487,11 +3489,11 @@ rs6000_legitimate_offset_address_p (enum machine_mode mode, rtx x, int strict) break; case TFmode: - case TDmode: if (TARGET_E500_DOUBLE) return (SPE_CONST_OFFSET_OK (offset) && SPE_CONST_OFFSET_OK (offset + 8)); + case TDmode: case TImode: if (mode == TFmode || mode == TDmode || !TARGET_POWERPC64) extra = 12; @@ -3638,7 +3640,8 @@ rs6000_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, && !(SPE_VECTOR_MODE (mode) || ALTIVEC_VECTOR_MODE (mode) || (TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode - || mode == DImode)))) + || mode == DImode || mode == DDmode + || mode == TDmode)))) { HOST_WIDE_INT high_int, low_int; rtx sum; @@ -3655,7 +3658,7 @@ rs6000_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, && ((TARGET_HARD_FLOAT && TARGET_FPRS) || TARGET_POWERPC64 || ((mode != DImode && mode != DFmode && mode != DDmode) - || TARGET_E500_DOUBLE)) + || (TARGET_E500_DOUBLE && mode != DDmode))) && (TARGET_POWERPC64 || mode != DImode) && mode != TImode && mode != TFmode @@ -3704,7 +3707,7 @@ rs6000_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, reg + offset] is not a legitimate addressing mode. */ y = gen_rtx_PLUS (Pmode, op1, op2); - if (GET_MODE_SIZE (mode) > 8 && REG_P (op2)) + if ((GET_MODE_SIZE (mode) > 8 || mode == DDmode) && REG_P (op2)) return force_reg (Pmode, y); else return y; @@ -4265,7 +4268,8 @@ rs6000_legitimate_address (enum machine_mode mode, rtx x, int reg_ok_strict) && mode != TDmode && ((TARGET_HARD_FLOAT && TARGET_FPRS) || TARGET_POWERPC64 - || ((mode != DFmode && mode != DDmode) || TARGET_E500_DOUBLE)) + || (mode != DFmode && mode != DDmode) + || (TARGET_E500_DOUBLE && mode != DDmode)) && (TARGET_POWERPC64 || mode != DImode) && legitimate_indexed_address_p (x, reg_ok_strict)) return 1; @@ -4389,7 +4393,8 @@ rs6000_hard_regno_nregs (int regno, enum machine_mode mode) would require function_arg and rs6000_spe_function_arg to handle SCmode so as to pass the value correctly in a pair of registers. */ - if (TARGET_E500_DOUBLE && FLOAT_MODE_P (mode) && mode != SCmode) + if (TARGET_E500_DOUBLE && FLOAT_MODE_P (mode) && mode != SCmode + && !DECIMAL_FLOAT_MODE_P (mode)) return (GET_MODE_SIZE (mode) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD; return (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD; @@ -5664,14 +5669,12 @@ spe_build_register_parallel (enum machine_mode mode, int gregno) switch (mode) { case DFmode: - case DDmode: r1 = gen_rtx_REG (DImode, gregno); r1 = gen_rtx_EXPR_LIST (VOIDmode, r1, const0_rtx); return gen_rtx_PARALLEL (mode, gen_rtvec (1, r1)); case DCmode: case TFmode: - case TDmode: r1 = gen_rtx_REG (DImode, gregno); r1 = gen_rtx_EXPR_LIST (VOIDmode, r1, const0_rtx); r3 = gen_rtx_REG (DImode, gregno + 2); @@ -5704,13 +5707,12 @@ rs6000_spe_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, /* On E500 v2, double arithmetic is done on the full 64-bit GPR, but are passed and returned in a pair of GPRs for ABI compatibility. */ if (TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode - || mode == DDmode || mode == TDmode || mode == DCmode || mode == TCmode)) { int n_words = rs6000_arg_size (mode, type); /* Doubles go in an odd/even register pair (r5/r6, etc). */ - if (mode == DFmode || mode == DDmode) + if (mode == DFmode) gregno += (1 - gregno) & 1; /* Multi-reg args are not split between registers and stack. */ @@ -6123,10 +6125,8 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, else if (TARGET_SPE_ABI && TARGET_SPE && (SPE_VECTOR_MODE (mode) || (TARGET_E500_DOUBLE && (mode == DFmode - || mode == DDmode || mode == DCmode || mode == TFmode - || mode == TDmode || mode == TCmode)))) return rs6000_spe_function_arg (cum, mode, type); @@ -6885,7 +6885,9 @@ rs6000_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p) /* _Decimal32 varargs are located in the second word of the 64-bit FP register for 32-bit binaries. */ - if (!TARGET_POWERPC64 && TYPE_MODE (type) == SDmode) + if (!TARGET_POWERPC64 + && TARGET_HARD_FLOAT && TARGET_FPRS + && TYPE_MODE (type) == SDmode) t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (t), t, size_int (size)); t = build2 (GIMPLE_MODIFY_STMT, void_type_node, addr, t); @@ -14015,8 +14017,8 @@ rs6000_split_multireg_move (rtx dst, rtx src) reg_mode = DECIMAL_FLOAT_MODE_P (mode) ? DDmode : DFmode; else if (ALTIVEC_REGNO_P (reg)) reg_mode = V16QImode; - else if (TARGET_E500_DOUBLE && (mode == TFmode || mode == TDmode)) - reg_mode = DECIMAL_FLOAT_MODE_P (mode) ? DDmode : DFmode; + else if (TARGET_E500_DOUBLE && mode == TFmode) + reg_mode = DFmode; else reg_mode = word_mode; reg_mode_size = GET_MODE_SIZE (reg_mode); @@ -14757,8 +14759,7 @@ spe_func_has_64bit_regs_p (void) if (SPE_VECTOR_MODE (mode)) return true; - if (TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode - || mode == DDmode || mode == TDmode)) + if (TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode)) return true; } } @@ -15509,7 +15510,7 @@ emit_frame_save (rtx frame_reg, rtx frame_ptr, enum machine_mode mode, /* Some cases that need register indexed addressing. */ if ((TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode)) - || (TARGET_E500_DOUBLE && (mode == DFmode || mode == DDmode)) + || (TARGET_E500_DOUBLE && mode == DFmode) || (TARGET_SPE_ABI && SPE_VECTOR_MODE (mode) && !SPE_CONST_OFFSET_OK (offset))) @@ -15549,7 +15550,7 @@ gen_frame_mem_offset (enum machine_mode mode, rtx reg, int offset) int_rtx = GEN_INT (offset); if ((TARGET_SPE_ABI && SPE_VECTOR_MODE (mode)) - || (TARGET_E500_DOUBLE && (mode == DFmode || mode == DDmode))) + || (TARGET_E500_DOUBLE && mode == DFmode)) { offset_rtx = gen_rtx_REG (Pmode, FIXED_SCRATCH); emit_move_insn (offset_rtx, int_rtx); @@ -21864,8 +21865,8 @@ rs6000_function_value (const_tree valtype, const_tree func ATTRIBUTE_UNUSED) && ALTIVEC_VECTOR_MODE (mode)) regno = ALTIVEC_ARG_RETURN; else if (TARGET_E500_DOUBLE && TARGET_HARD_FLOAT - && (mode == DFmode || mode == DDmode || mode == DCmode - || mode == TFmode || mode == TDmode || mode == TCmode)) + && (mode == DFmode || mode == DCmode + || mode == TFmode || mode == TCmode)) return spe_build_register_parallel (mode, GP_ARG_RETURN); else regno = GP_ARG_RETURN; @@ -21906,8 +21907,8 @@ rs6000_libcall_value (enum machine_mode mode) else if (COMPLEX_MODE_P (mode) && targetm.calls.split_complex_arg) return rs6000_complex_function_value (mode); else if (TARGET_E500_DOUBLE && TARGET_HARD_FLOAT - && (mode == DFmode || mode == DDmode || mode == DCmode - || mode == TFmode || mode == TDmode || mode == TCmode)) + && (mode == DFmode || mode == DCmode + || mode == TFmode || mode == TCmode)) return spe_build_register_parallel (mode, GP_ARG_RETURN); else regno = GP_ARG_RETURN; |