diff options
author | Aldy Hernandez <aldyh@redhat.com> | 2004-10-26 12:28:59 +0000 |
---|---|---|
committer | Aldy Hernandez <aldyh@gcc.gnu.org> | 2004-10-26 12:28:59 +0000 |
commit | f82f556dac8378f2c7e469b71e411ea721bc12e5 (patch) | |
tree | 0eed431f856523aba5fc164abfaa429854dfebfb | |
parent | 8db8c940f180e23567dab2fb34a27e272d27fe4c (diff) | |
download | gcc-f82f556dac8378f2c7e469b71e411ea721bc12e5.zip gcc-f82f556dac8378f2c7e469b71e411ea721bc12e5.tar.gz gcc-f82f556dac8378f2c7e469b71e411ea721bc12e5.tar.bz2 |
rs6000.c (rs6000_hard_regno_nregs): Adjust for e500 doubles.
* config/rs6000/rs6000.c (rs6000_hard_regno_nregs): Adjust for
e500 doubles.
(spe_build_register_parallel): New.
(rs6000_spe_function_arg): Handle e500 doubles.
(function_arg): Same.
(spe_func_has_64bit_regs_p): Same.
(rs6000_function_value): Same.
(rs6000_libcall_value): Same.
(legitimate_lo_sum_address_p): Return false for e500 doubles.
* config/rs6000/rs6000.h (LOCAL_ALIGNMENT): Adjust for e500
doubles.
(DATA_ALIGNMENT): Same.
(CANNOT_CHANGE_MODE_CLASS): Same.
From-SVN: r89582
-rw-r--r-- | gcc/ChangeLog | 17 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 68 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.h | 7 |
3 files changed, 81 insertions, 11 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 64fe9ab..bc2a4ec 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,22 @@ 2004-10-26 Aldy Hernandez <aldyh@redhat.com> + * config/rs6000/rs6000.c (rs6000_hard_regno_nregs): Adjust for + e500 doubles. + (spe_build_register_parallel): New. + (rs6000_spe_function_arg): Handle e500 doubles. + (function_arg): Same. + (spe_func_has_64bit_regs_p): Same. + (rs6000_function_value): Same. + (rs6000_libcall_value): Same. + (legitimate_lo_sum_address_p): Return false for e500 doubles. + + * config/rs6000/rs6000.h (LOCAL_ALIGNMENT): Adjust for e500 + doubles. + (DATA_ALIGNMENT): Same. + (CANNOT_CHANGE_MODE_CLASS): Same. + +2004-10-26 Aldy Hernandez <aldyh@redhat.com> + * expr.c (emit_group_load): Handle floats. (emit_group_store): Same. diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index adf4fec..6909859 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -3281,6 +3281,8 @@ legitimate_lo_sum_address_p (enum machine_mode mode, rtx x, int strict) return false; if (!INT_REG_OK_FOR_BASE_P (XEXP (x, 0), strict)) return false; + if (TARGET_E500_DOUBLE && mode == DFmode) + return false; x = XEXP (x, 1); if (TARGET_ELF || TARGET_MACHO) @@ -3418,8 +3420,7 @@ 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_E500_DOUBLE)) + && ((TARGET_HARD_FLOAT && TARGET_FPRS) || mode != DFmode) && mode != DImode && mode != TImode) { @@ -4933,15 +4934,50 @@ function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, } } -/* Determine where to put a SIMD argument on the SPE. */ +static rtx +spe_build_register_parallel (enum machine_mode mode, int gregno) +{ + rtx r1, r2; + enum machine_mode inner; + unsigned int inner_bytes; + + if (mode == DFmode) + { + inner = SImode; + inner_bytes = 4; + } + else + abort (); + + r1 = gen_rtx_REG (inner, gregno); + r1 = gen_rtx_EXPR_LIST (SImode, r1, const0_rtx); + r2 = gen_rtx_REG (inner, gregno + 1); + r2 = gen_rtx_EXPR_LIST (SImode, r2, GEN_INT (inner_bytes)); + return gen_rtx_PARALLEL (mode, gen_rtvec (2, r1, r2)); +} +/* Determine where to put a SIMD argument on the SPE. */ static rtx rs6000_spe_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type) { + int gregno = cum->sysv_gregno; + + /* 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 compatability. */ + if (TARGET_E500_DOUBLE && mode == DFmode) + { + /* Doubles go in an odd/even register pair (r5/r6, etc). */ + gregno += (1 - gregno) & 1; + + /* We do not split between registers and stack. */ + if (gregno + 1 > GP_ARG_MAX_REG) + return NULL_RTX; + + return spe_build_register_parallel (mode, gregno); + } if (cum->stdarg) { - int gregno = cum->sysv_gregno; int n_words = rs6000_arg_size (mode, type); /* SPE vectors are put in odd registers. */ @@ -4964,8 +5000,8 @@ rs6000_spe_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, } else { - if (cum->sysv_gregno <= GP_ARG_MAX_REG) - return gen_rtx_REG (mode, cum->sysv_gregno); + if (gregno <= GP_ARG_MAX_REG) + return gen_rtx_REG (mode, gregno); else return NULL_RTX; } @@ -5144,7 +5180,9 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, return gen_rtx_REG (part_mode, GP_ARG_MIN_REG + align_words); } } - else if (TARGET_SPE_ABI && TARGET_SPE && SPE_VECTOR_MODE (mode)) + else if (TARGET_SPE_ABI && TARGET_SPE + && (SPE_VECTOR_MODE (mode) + || (TARGET_E500_DOUBLE && mode == DFmode))) return rs6000_spe_function_arg (cum, mode, type); else if (abi == ABI_V4) { @@ -12543,9 +12581,15 @@ spe_func_has_64bit_regs_p (void) rtx i; i = PATTERN (insn); - if (GET_CODE (i) == SET - && SPE_VECTOR_MODE (GET_MODE (SET_SRC (i)))) - return true; + if (GET_CODE (i) == SET) + { + enum machine_mode mode = GET_MODE (SET_SRC (i)); + + if (SPE_VECTOR_MODE (mode)) + return true; + if (TARGET_E500_DOUBLE && mode == DFmode) + return true; + } } } @@ -18078,6 +18122,8 @@ rs6000_function_value (tree valtype, tree func ATTRIBUTE_UNUSED) && TARGET_ALTIVEC && TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE(mode)) regno = ALTIVEC_ARG_RETURN; + else if (TARGET_E500_DOUBLE && TARGET_HARD_FLOAT && mode == DFmode) + return spe_build_register_parallel (DFmode, GP_ARG_RETURN); else regno = GP_ARG_RETURN; @@ -18113,6 +18159,8 @@ rs6000_libcall_value (enum machine_mode mode) regno = ALTIVEC_ARG_RETURN; 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) + return spe_build_register_parallel (DFmode, GP_ARG_RETURN); else regno = GP_ARG_RETURN; diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index 0a209b6..a64d682 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -742,6 +742,7 @@ extern const char *rs6000_warn_altivec_long_switch; that the object would ordinarily have. */ #define LOCAL_ALIGNMENT(TYPE, ALIGN) \ ((TARGET_ALTIVEC && TREE_CODE (TYPE) == VECTOR_TYPE) ? 128 : \ + (TARGET_E500_DOUBLE && TYPE_MODE (TYPE) == DFmode) ? 64 : \ (TARGET_SPE && TREE_CODE (TYPE) == VECTOR_TYPE) ? 64 : ALIGN) /* Alignment of field after `int : 0' in a structure. */ @@ -774,9 +775,11 @@ extern const char *rs6000_warn_altivec_long_switch; : (ALIGN)) /* Make arrays of chars word-aligned for the same reasons. - Align vectors to 128 bits. */ + Align vectors to 128 bits. Align SPE vectors and E500 v2 doubles to + 64 bits. */ #define DATA_ALIGNMENT(TYPE, ALIGN) \ (TREE_CODE (TYPE) == VECTOR_TYPE ? (TARGET_SPE_ABI ? 64 : 128) \ + : (TARGET_E500_DOUBLE && TYPE_MODE (TYPE) == DFmode) ? 64 \ : TREE_CODE (TYPE) == ARRAY_TYPE \ && TYPE_MODE (TREE_TYPE (TYPE)) == QImode \ && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN)) @@ -1433,6 +1436,8 @@ enum reg_class ? 0 \ : GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \ ? reg_classes_intersect_p (FLOAT_REGS, CLASS) \ + : (TARGET_E500_DOUBLE && (((TO) == DFmode) + ((FROM) == DFmode)) == 1) \ + ? reg_classes_intersect_p (GENERAL_REGS, CLASS) \ : (TARGET_SPE && (SPE_VECTOR_MODE (FROM) + SPE_VECTOR_MODE (TO)) == 1) \ ? reg_classes_intersect_p (GENERAL_REGS, CLASS) \ : 0) |