diff options
Diffstat (limited to 'gcc/config/rs6000/rs6000.c')
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 140 |
1 files changed, 109 insertions, 31 deletions
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 7d2d1d9b794..6117bdb6b60 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -723,6 +723,7 @@ static void rs6000_parse_abi_options (void); static void rs6000_parse_alignment_option (void); static void rs6000_parse_tls_size_option (void); static void rs6000_parse_yes_no_option (const char *, const char *, int *); +static void rs6000_parse_float_gprs_option (void); static int first_altivec_reg_to_save (void); static unsigned int compute_vrsave_mask (void); static void compute_save_world_info(rs6000_stack_t *info_ptr); @@ -1119,6 +1120,8 @@ rs6000_override_options (const char *default_cpu) {"821", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT}, {"823", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT}, {"8540", PROCESSOR_PPC8540, POWERPC_BASE_MASK | MASK_PPC_GFXOPT}, + /* 8548 has a dummy entry for now. */ + {"8548", PROCESSOR_PPC8540, POWERPC_BASE_MASK | MASK_PPC_GFXOPT}, {"860", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT}, {"970", PROCESSOR_POWER4, POWERPC_7400_MASK | MASK_PPC_GPOPT | MASK_MFCRF | MASK_POWERPC64}, @@ -1292,14 +1295,14 @@ rs6000_override_options (const char *default_cpu) /* Handle -malign-XXXXX option. */ rs6000_parse_alignment_option (); + rs6000_parse_float_gprs_option (); + /* Handle generic -mFOO=YES/NO options. */ rs6000_parse_yes_no_option ("vrsave", rs6000_altivec_vrsave_string, &rs6000_altivec_vrsave); rs6000_parse_yes_no_option ("isel", rs6000_isel_string, &rs6000_isel); rs6000_parse_yes_no_option ("spe", rs6000_spe_string, &rs6000_spe); - rs6000_parse_yes_no_option ("float-gprs", rs6000_float_gprs_string, - &rs6000_float_gprs); /* Handle -mtls-size option. */ rs6000_parse_tls_size_option (); @@ -1310,6 +1313,9 @@ rs6000_override_options (const char *default_cpu) #ifdef SUBSUBTARGET_OVERRIDE_OPTIONS SUBSUBTARGET_OVERRIDE_OPTIONS; #endif +#ifdef SUB3TARGET_OVERRIDE_OPTIONS + SUB3TARGET_OVERRIDE_OPTIONS; +#endif if (TARGET_E500) { @@ -1622,6 +1628,23 @@ rs6000_parse_abi_options (void) error ("unknown ABI specified: '%s'", rs6000_abi_string); } +/* Handle -mfloat-gprs= options. */ +static void +rs6000_parse_float_gprs_option (void) +{ + if (rs6000_float_gprs_string == 0) + return; + else if (! strcmp (rs6000_float_gprs_string, "yes") + || ! strcmp (rs6000_float_gprs_string, "single")) + rs6000_float_gprs = 1; + else if (! strcmp (rs6000_float_gprs_string, "double")) + rs6000_float_gprs = 2; + else if (! strcmp (rs6000_float_gprs_string, "no")) + rs6000_float_gprs = 0; + else + error ("invalid option for -mfloat-gprs"); +} + /* Handle -malign-XXXXXX options. */ static void rs6000_parse_alignment_option (void) @@ -2163,7 +2186,7 @@ easy_fp_constant (rtx op, enum machine_mode mode) return 0; /* Consider all constants with -msoft-float to be easy. */ - if ((TARGET_SOFT_FLOAT || !TARGET_FPRS) + if ((TARGET_SOFT_FLOAT || TARGET_E500_SINGLE) && mode != DImode) return 1; @@ -2197,6 +2220,9 @@ easy_fp_constant (rtx op, enum machine_mode mode) long k[2]; REAL_VALUE_TYPE rv; + if (TARGET_E500_DOUBLE) + return 0; + REAL_VALUE_FROM_CONST_DOUBLE (rv, op); REAL_VALUE_TO_TARGET_DOUBLE (rv, k); @@ -3173,6 +3199,9 @@ rs6000_legitimate_offset_address_p (enum machine_mode mode, rtx x, int strict) return SPE_CONST_OFFSET_OK (offset); case DFmode: + if (TARGET_E500_DOUBLE) + return SPE_CONST_OFFSET_OK (offset); + case DImode: if (mode == DFmode || !TARGET_POWERPC64) extra = 4; @@ -3325,7 +3354,7 @@ rs6000_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, && GET_MODE_NUNITS (mode) == 1 && ((TARGET_HARD_FLOAT && TARGET_FPRS) || TARGET_POWERPC64 - || (mode != DFmode && mode != TFmode)) + || ((mode != DFmode || TARGET_E500_DOUBLE) && mode != TFmode)) && (TARGET_POWERPC64 || mode != DImode) && mode != TImode) { @@ -3344,7 +3373,8 @@ rs6000_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, reg = force_reg (Pmode, x); return reg; } - else if (SPE_VECTOR_MODE (mode)) + else if (SPE_VECTOR_MODE (mode) + || (TARGET_E500_DOUBLE && mode == DFmode)) { /* We accept [reg + reg] and [reg + OFFSET]. */ @@ -3388,7 +3418,8 @@ rs6000_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, && GET_CODE (x) != CONST_INT && GET_CODE (x) != CONST_DOUBLE && CONSTANT_P (x) - && ((TARGET_HARD_FLOAT && TARGET_FPRS) || mode != DFmode) + && ((TARGET_HARD_FLOAT && TARGET_FPRS) + || (mode != DFmode || TARGET_E500_DOUBLE)) && mode != DImode && mode != TImode) { @@ -3735,6 +3766,7 @@ rs6000_legitimize_reload_address (rtx x, enum machine_mode mode, && REG_MODE_OK_FOR_BASE_P (XEXP (x, 0), mode) && GET_CODE (XEXP (x, 1)) == CONST_INT && !SPE_VECTOR_MODE (mode) + && !(TARGET_E500_DOUBLE && mode == DFmode) && !ALTIVEC_VECTOR_MODE (mode)) { HOST_WIDE_INT val = INTVAL (XEXP (x, 1)); @@ -3838,6 +3870,7 @@ rs6000_legitimate_address (enum machine_mode mode, rtx x, int reg_ok_strict) if ((GET_CODE (x) == PRE_INC || GET_CODE (x) == PRE_DEC) && !ALTIVEC_VECTOR_MODE (mode) && !SPE_VECTOR_MODE (mode) + && !(TARGET_E500_DOUBLE && mode == DFmode) && TARGET_UPDATE && legitimate_indirect_address_p (XEXP (x, 0), reg_ok_strict)) return 1; @@ -3859,7 +3892,7 @@ rs6000_legitimate_address (enum machine_mode mode, rtx x, int reg_ok_strict) && mode != TFmode && ((TARGET_HARD_FLOAT && TARGET_FPRS) || TARGET_POWERPC64 - || (mode != DFmode && mode != TFmode)) + || ((mode != DFmode || TARGET_E500_DOUBLE) && mode != TFmode)) && (TARGET_POWERPC64 || mode != DImode) && legitimate_indexed_address_p (x, reg_ok_strict)) return 1; @@ -3924,6 +3957,9 @@ rs6000_hard_regno_nregs (int regno, enum machine_mode mode) if (FP_REGNO_P (regno)) return (GET_MODE_SIZE (mode) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD; + if (TARGET_E500_DOUBLE && mode == DFmode) + return 1; + if (SPE_SIMD_REGNO_P (regno) && TARGET_SPE && SPE_VECTOR_MODE (mode)) return (GET_MODE_SIZE (mode) + UNITS_PER_SPE_WORD - 1) / UNITS_PER_SPE_WORD; @@ -10864,6 +10900,10 @@ rs6000_generate_compare (enum rtx_code code) && rs6000_compare_fp_p) { rtx cmp, or1, or2, or_result, compare_result2; + enum machine_mode op_mode = GET_MODE (rs6000_compare_op0); + + if (op_mode == VOIDmode) + op_mode = GET_MODE (rs6000_compare_op1); /* Note: The E500 comparison instructions set the GT bit (x + 1), on success. This explains the mess. */ @@ -10871,28 +10911,52 @@ rs6000_generate_compare (enum rtx_code code) switch (code) { case EQ: case UNEQ: case NE: case LTGT: - cmp = flag_finite_math_only - ? gen_tstsfeq_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1) - : gen_cmpsfeq_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1); + if (op_mode == SFmode) + cmp = flag_finite_math_only + ? gen_tstsfeq_gpr (compare_result, rs6000_compare_op0, + rs6000_compare_op1) + : gen_cmpsfeq_gpr (compare_result, rs6000_compare_op0, + rs6000_compare_op1); + else if (op_mode == DFmode) + cmp = flag_finite_math_only + ? gen_tstdfeq_gpr (compare_result, rs6000_compare_op0, + rs6000_compare_op1) + : gen_cmpdfeq_gpr (compare_result, rs6000_compare_op0, + rs6000_compare_op1); + else abort (); break; case GT: case GTU: case UNGT: case UNGE: case GE: case GEU: - cmp = flag_finite_math_only - ? gen_tstsfgt_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1) - : gen_cmpsfgt_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1); + if (op_mode == SFmode) + cmp = flag_finite_math_only + ? gen_tstsfgt_gpr (compare_result, rs6000_compare_op0, + rs6000_compare_op1) + : gen_cmpsfgt_gpr (compare_result, rs6000_compare_op0, + rs6000_compare_op1); + else if (op_mode == DFmode) + cmp = flag_finite_math_only + ? gen_tstdfgt_gpr (compare_result, rs6000_compare_op0, + rs6000_compare_op1) + : gen_cmpdfgt_gpr (compare_result, rs6000_compare_op0, + rs6000_compare_op1); + else abort (); break; case LT: case LTU: case UNLT: case UNLE: case LE: case LEU: - cmp = flag_finite_math_only - ? gen_tstsflt_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1) - : gen_cmpsflt_gpr (compare_result, rs6000_compare_op0, - rs6000_compare_op1); + if (op_mode == SFmode) + cmp = flag_finite_math_only + ? gen_tstsflt_gpr (compare_result, rs6000_compare_op0, + rs6000_compare_op1) + : gen_cmpsflt_gpr (compare_result, rs6000_compare_op0, + rs6000_compare_op1); + else if (op_mode == DFmode) + cmp = flag_finite_math_only + ? gen_tstdflt_gpr (compare_result, rs6000_compare_op0, + rs6000_compare_op1) + : gen_cmpdflt_gpr (compare_result, rs6000_compare_op0, + rs6000_compare_op1); + else abort (); break; - default: - abort (); + default: + abort (); } /* Synthesize LE and GE from LT/GT || EQ. */ @@ -10915,11 +10979,19 @@ rs6000_generate_compare (enum rtx_code code) compare_result2 = gen_reg_rtx (CCFPmode); /* Do the EQ. */ - cmp = flag_finite_math_only - ? gen_tstsfeq_gpr (compare_result2, rs6000_compare_op0, - rs6000_compare_op1) - : gen_cmpsfeq_gpr (compare_result2, rs6000_compare_op0, - rs6000_compare_op1); + if (op_mode == SFmode) + cmp = flag_finite_math_only + ? gen_tstsfeq_gpr (compare_result2, rs6000_compare_op0, + rs6000_compare_op1) + : gen_cmpsfeq_gpr (compare_result2, rs6000_compare_op0, + rs6000_compare_op1); + else if (op_mode == DFmode) + cmp = flag_finite_math_only + ? gen_tstdfeq_gpr (compare_result2, rs6000_compare_op0, + rs6000_compare_op1) + : gen_cmpdfeq_gpr (compare_result2, rs6000_compare_op0, + rs6000_compare_op1); + else abort (); emit_insn (cmp); or1 = gen_rtx_GT (SImode, compare_result, const0_rtx); @@ -13289,6 +13361,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) || (TARGET_SPE_ABI && SPE_VECTOR_MODE (mode) && !SPE_CONST_OFFSET_OK (offset))) @@ -13328,7 +13401,8 @@ 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)) + if ((TARGET_SPE_ABI && SPE_VECTOR_MODE (mode)) + || (TARGET_E500_DOUBLE && mode == DFmode)) { offset_rtx = gen_rtx_REG (Pmode, FIXED_SCRATCH); emit_move_insn (offset_rtx, int_rtx); @@ -18082,7 +18156,11 @@ rs6000_dwarf_register_span (rtx reg) { unsigned regno; - if (!TARGET_SPE || !SPE_VECTOR_MODE (GET_MODE (reg))) + if (TARGET_SPE + && (SPE_VECTOR_MODE (GET_MODE (reg)) + || (TARGET_E500_DOUBLE && GET_MODE (reg) == DFmode))) + ; + else return NULL_RTX; regno = REGNO (reg); |