From d8e6ba8f2a5f94dc7aa57c6960afe52fa0a666a9 Mon Sep 17 00:00:00 2001 From: amylaar Date: Tue, 24 Jun 2003 17:22:05 +0000 Subject: [PATCH] Back out these patches: 2003-06-02 J"orn Rennecke * sh.h (OLD_ARG_MODE): New macro. (FUNCTION_ARG_ADVANCE, FUNCTION_ARG_PASS_BY_REFERENCE): Use it. (FUNCTION_ARG_1): Break out of: (FUNCTION_ARG). Use OLD_ARG_MODE. 2003-06-06 J"orn Rennecke * sh.h (FUNCTION_ARG_1): Consistently use NEW_MODE for the mode of the generated register. * sh.h (FUNCTION_ARG_SCmode_WART): Define. (FUNCTION_ARG): Unless FUNCTION_ARG_SCmode_WART is defined and an even number of floating point regs are in use, use the same sequence of argument passing registers for SCmode as would be used for two SFmode values. * sh.c (sh_va_arg): If FUNCTION_ARG_SCmode_WART is defined, swap real / imaginary parts in incoming SCmode values passed in registers. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@68430 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 21 ++++++++++++ gcc/config/sh/sh.c | 65 ++++++++++++++++++++++++++++++++---- gcc/config/sh/sh.h | 96 ++++++++++++++++++++++++++++++++++-------------------- 3 files changed, 139 insertions(+), 43 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 53609e41cd5..6b63396325f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,24 @@ +2003-06-24 J"orn Rennecke + + Back out these patches: + 2003-06-02 J"orn Rennecke + * sh.h (OLD_ARG_MODE): New macro. + (FUNCTION_ARG_ADVANCE, FUNCTION_ARG_PASS_BY_REFERENCE): Use it. + (FUNCTION_ARG_1): Break out of: + (FUNCTION_ARG). Use OLD_ARG_MODE. + 2003-06-06 J"orn Rennecke + * sh.h (FUNCTION_ARG_1): Consistently use NEW_MODE for the mode + of the generated register. + + * sh.h (FUNCTION_ARG_SCmode_WART): Define. + (FUNCTION_ARG): Unless FUNCTION_ARG_SCmode_WART is defined and + an even number of floating point regs are in use, use the same + sequence of argument passing registers for SCmode as would be + used for two SFmode values. + * sh.c (sh_va_arg): If FUNCTION_ARG_SCmode_WART is defined, + swap real / imaginary parts in incoming SCmode values passed + in registers. + 2003-06-24 Falk Hueffner PR target/11260 diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index 070e4093e20..aab3c3945b3 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -5940,8 +5940,9 @@ sh_va_arg (valist, type) HOST_WIDE_INT size, rsize; tree tmp, pptr_type_node; rtx addr_rtx, r; - rtx result; + rtx result_ptr, result = NULL_RTX; int pass_by_ref = MUST_PASS_IN_STACK (TYPE_MODE (type), type); + rtx lab_over; size = int_size_in_bytes (type); rsize = (size + UNITS_PER_WORD - 1) & -UNITS_PER_WORD; @@ -5955,7 +5956,7 @@ sh_va_arg (valist, type) tree f_next_o, f_next_o_limit, f_next_fp, f_next_fp_limit, f_next_stack; tree next_o, next_o_limit, next_fp, next_fp_limit, next_stack; int pass_as_float; - rtx lab_false, lab_over; + rtx lab_false; f_next_o = TYPE_FIELDS (va_list_type_node); f_next_o_limit = TREE_CHAIN (f_next_o); @@ -5973,6 +5974,16 @@ sh_va_arg (valist, type) next_stack = build (COMPONENT_REF, TREE_TYPE (f_next_stack), valist, f_next_stack); + /* Structures with a single member with a distinct mode are passed + like their member. This is relevant if the latter has a REAL_TYPE + or COMPLEX_TYPE type. */ + if (TREE_CODE (type) == RECORD_TYPE + && TYPE_FIELDS (type) + && TREE_CODE (TYPE_FIELDS (type)) == FIELD_DECL + && (TREE_CODE (TREE_TYPE (TYPE_FIELDS (type))) == REAL_TYPE + || TREE_CODE (TREE_TYPE (TYPE_FIELDS (type))) == COMPLEX_TYPE) + && TREE_CHAIN (TYPE_FIELDS (type)) == NULL_TREE) + type = TREE_TYPE (TYPE_FIELDS (type)); if (TARGET_SH4) { pass_as_float = ((TREE_CODE (type) == REAL_TYPE && size <= 8) @@ -5989,6 +6000,9 @@ sh_va_arg (valist, type) lab_false = gen_label_rtx (); lab_over = gen_label_rtx (); + tmp = make_tree (pptr_type_node, addr_rtx); + valist = build1 (INDIRECT_REF, ptr_type_node, tmp); + if (pass_as_float) { int first_floatreg @@ -6018,6 +6032,37 @@ sh_va_arg (valist, type) if (r != addr_rtx) emit_move_insn (addr_rtx, r); +#ifdef FUNCTION_ARG_SCmode_WART + if (TYPE_MODE (type) == SCmode && TARGET_SH4 && TARGET_LITTLE_ENDIAN) + { + rtx addr, real, imag, result_value, slot; + tree subtype = TREE_TYPE (type); + + addr = std_expand_builtin_va_arg (valist, subtype); +#ifdef POINTERS_EXTEND_UNSIGNED + if (GET_MODE (addr) != Pmode) + addr = convert_memory_address (Pmode, addr); +#endif + imag = gen_rtx_MEM (TYPE_MODE (type), addr); + set_mem_alias_set (imag, get_varargs_alias_set ()); + + addr = std_expand_builtin_va_arg (valist, subtype); +#ifdef POINTERS_EXTEND_UNSIGNED + if (GET_MODE (addr) != Pmode) + addr = convert_memory_address (Pmode, addr); +#endif + real = gen_rtx_MEM (TYPE_MODE (type), addr); + set_mem_alias_set (real, get_varargs_alias_set ()); + + result_value = gen_rtx_CONCAT (SCmode, real, imag); + /* ??? this interface is stupid - why require a pointer? */ + result = gen_reg_rtx (Pmode); + slot = assign_stack_temp (SCmode, 8, 0); + emit_move_insn (slot, result_value); + emit_move_insn (result, XEXP (slot, 0)); + } +#endif /* FUNCTION_ARG_SCmode_WART */ + emit_jump_insn (gen_jump (lab_over)); emit_barrier (); emit_label (lab_false); @@ -6060,16 +6105,22 @@ sh_va_arg (valist, type) emit_move_insn (addr_rtx, r); } - emit_label (lab_over); - - tmp = make_tree (pptr_type_node, addr_rtx); - valist = build1 (INDIRECT_REF, ptr_type_node, tmp); + if (! result) + emit_label (lab_over); } /* ??? In va-sh.h, there had been code to make values larger than size 8 indirect. This does not match the FUNCTION_ARG macros. */ - result = std_expand_builtin_va_arg (valist, type); + result_ptr = std_expand_builtin_va_arg (valist, type); + if (result) + { + emit_move_insn (result, result_ptr); + emit_label (lab_over); + } + else + result = result_ptr; + if (pass_by_ref) { #ifdef POINTERS_EXTEND_UNSIGNED diff --git a/gcc/config/sh/sh.h b/gcc/config/sh/sh.h index 2c62d4705a9..ee49f6b9a79 100644 --- a/gcc/config/sh/sh.h +++ b/gcc/config/sh/sh.h @@ -1867,20 +1867,12 @@ struct sh_args { (CUM).outgoing = 0; \ } while (0) -#define OLD_ARG_MODE(MODE, TYPE) \ - (((TYPE) \ - && (TREE_CODE (TYPE) == RECORD_TYPE || TREE_CODE (TYPE) == UNION_TYPE) \ - && (MODE) != BLKmode && GET_MODE_CLASS (MODE) != MODE_INT) \ - ? int_mode_for_mode (MODE) : (MODE)) - /* Update the data in CUM to advance over an argument of mode MODE and data type TYPE. (TYPE is null for libcalls where that information may not be available.) */ #define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ -do { \ - enum machine_mode MODE_ = OLD_ARG_MODE ((MODE), (TYPE));\ if ((CUM).force_mem) \ (CUM).force_mem = 0; \ else if (TARGET_SH5) \ @@ -1888,17 +1880,17 @@ do { \ tree TYPE_ = ((CUM).byref && (TYPE) \ ? TREE_TYPE (TYPE) \ : (TYPE)); \ - int dwords, numregs; \ + enum machine_mode MODE_ = ((CUM).byref && (TYPE) \ + ? TYPE_MODE (TYPE_) \ + : (MODE)); \ + int dwords = (((CUM).byref \ + ? (CUM).byref \ + : (MODE_) == BLKmode \ + ? int_size_in_bytes (TYPE_) \ + : GET_MODE_SIZE (MODE_)) + 7) / 8; \ + int numregs = MIN (dwords, NPARM_REGS (SImode) \ + - (CUM).arg_count[(int) SH_ARG_INT]); \ \ - MODE_ = ((CUM).byref && (TYPE) \ - ? TYPE_MODE (TYPE_) : (MODE_)); \ - dwords = (((CUM).byref \ - ? (CUM).byref \ - : (MODE_) == BLKmode \ - ? int_size_in_bytes (TYPE_) \ - : GET_MODE_SIZE (MODE_)) + 7) / 8; \ - numregs = MIN (dwords, NPARM_REGS (SImode) \ - - (CUM).arg_count[(int) SH_ARG_INT]); \ if (numregs) \ { \ (CUM).arg_count[(int) SH_ARG_INT] += numregs; \ @@ -1990,13 +1982,12 @@ do { \ } \ } \ } \ - else if (! TARGET_SH4 || PASS_IN_REG_P ((CUM), (MODE_), (TYPE))) \ - ((CUM).arg_count[(int) GET_SH_ARG_CLASS (MODE_)] \ - = (ROUND_REG ((CUM), (MODE_)) \ - + ((MODE_) == BLKmode \ + else if (! TARGET_SH4 || PASS_IN_REG_P ((CUM), (MODE), (TYPE))) \ + ((CUM).arg_count[(int) GET_SH_ARG_CLASS (MODE)] \ + = (ROUND_REG ((CUM), (MODE)) \ + + ((MODE) == BLKmode \ ? ROUND_ADVANCE (int_size_in_bytes (TYPE)) \ - : ROUND_ADVANCE (GET_MODE_SIZE (MODE_))))); \ -} while (0) + : ROUND_ADVANCE (GET_MODE_SIZE (MODE))))) /* Return boolean indicating arg of mode MODE will be passed in a reg. This macro is only used in this file. */ @@ -2016,6 +2007,24 @@ do { \ <= NPARM_REGS (MODE))) \ : ROUND_REG ((CUM), (MODE)) < NPARM_REGS (MODE))) +/* By accident we got stuck with passing SCmode on SH4 little endian + in two registers that are nominally successive - which is different from + two single SFmode values, where we take endianness translation into + account. That does not work at all if an odd number of registers is + already in use, so that got fixed, but library functions are still more + likely to use complex numbers without mixing them with SFmode arguments + (which in C would have to be structures), so for the sake of ABI + compatibility the way SCmode values are passed when an even number of + FP registers is in use remains different from a pair of SFmode values for + now. + I.e.: + foo (double); a: fr5,fr4 + foo (float a, float b); a: fr5 b: fr4 + foo (__complex float a); a.real fr4 a.imag: fr5 - for consistency, + this should be the other way round... + foo (float a, __complex float b); a: fr5 b.real: fr4 b.imag: fr7 */ +#define FUNCTION_ARG_SCmode_WART 1 + /* Define where to put the arguments to a function. Value is zero to push the argument on the stack, or a hard register in which to store the argument. @@ -2035,29 +2044,44 @@ do { \ its data type forbids. */ #define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ - FUNCTION_ARG_1 ((CUM), OLD_ARG_MODE ((MODE), (TYPE)), (MODE), (TYPE), (NAMED)) - -#define FUNCTION_ARG_1(CUM, MODE, NEW_MODE, TYPE, NAMED) \ ((! TARGET_SH5 \ && PASS_IN_REG_P ((CUM), (MODE), (TYPE)) \ && ((NAMED) || !TARGET_HITACHI)) \ - ? gen_rtx_REG ((NEW_MODE), \ - ((BASE_ARG_REG (MODE) + ROUND_REG ((CUM), (MODE))) \ - ^ ((MODE) == SFmode && TARGET_SH4 \ - && TARGET_LITTLE_ENDIAN != 0))) \ + ? (((MODE) == SCmode && TARGET_SH4 && TARGET_LITTLE_ENDIAN \ + && (! FUNCTION_ARG_SCmode_WART || (ROUND_REG ((CUM), (MODE)) & 1)))\ + ? (gen_rtx_PARALLEL \ + (SCmode, \ + (gen_rtvec \ + (2, \ + (gen_rtx_EXPR_LIST \ + (VOIDmode, \ + gen_rtx_REG (SFmode, \ + BASE_ARG_REG (MODE) \ + + ROUND_REG ((CUM), (MODE)) ^ 1), \ + const0_rtx)), \ + (gen_rtx_EXPR_LIST \ + (VOIDmode, \ + gen_rtx_REG (SFmode, \ + BASE_ARG_REG (MODE) \ + + (ROUND_REG ((CUM), (MODE)) + 1) ^ 1), \ + GEN_INT (4))))))) \ + : gen_rtx_REG ((MODE), \ + ((BASE_ARG_REG (MODE) + ROUND_REG ((CUM), (MODE))) \ + ^ ((MODE) == SFmode && TARGET_SH4 \ + && TARGET_LITTLE_ENDIAN != 0)))) \ : TARGET_SH5 \ ? ((MODE) == VOIDmode && TARGET_SHCOMPACT \ ? GEN_INT ((CUM).call_cookie) \ /* The following test assumes unnamed arguments are promoted to \ DFmode. */ \ : (MODE) == SFmode && (CUM).free_single_fp_reg \ - ? SH5_PROTOTYPED_FLOAT_ARG ((CUM), (NEW_MODE), (CUM).free_single_fp_reg) \ + ? SH5_PROTOTYPED_FLOAT_ARG ((CUM), (MODE), (CUM).free_single_fp_reg) \ : (GET_SH_ARG_CLASS (MODE) == SH_ARG_FLOAT \ && ((NAMED) || ! (CUM).prototype_p) \ && (CUM).arg_count[(int) SH_ARG_FLOAT] < NPARM_REGS (SFmode)) \ ? ((! (CUM).prototype_p && TARGET_SHMEDIA) \ - ? SH5_PROTOTYPELESS_FLOAT_ARG ((CUM), (NEW_MODE)) \ - : SH5_PROTOTYPED_FLOAT_ARG ((CUM), (NEW_MODE), \ + ? SH5_PROTOTYPELESS_FLOAT_ARG ((CUM), (MODE)) \ + : SH5_PROTOTYPED_FLOAT_ARG ((CUM), (MODE), \ FIRST_FP_PARM_REG \ + (CUM).arg_count[(int) SH_ARG_FLOAT])) \ : ((CUM).arg_count[(int) SH_ARG_INT] < NPARM_REGS (SImode) \ @@ -2065,7 +2089,7 @@ do { \ || (! SHCOMPACT_FORCE_ON_STACK ((MODE), (TYPE)) \ && ! SH5_WOULD_BE_PARTIAL_NREGS ((CUM), (MODE), \ (TYPE), (NAMED))))) \ - ? gen_rtx_REG ((NEW_MODE), (FIRST_PARM_REG \ + ? gen_rtx_REG ((MODE), (FIRST_PARM_REG \ + (CUM).arg_count[(int) SH_ARG_INT])) \ : 0) \ : 0) @@ -2076,7 +2100,7 @@ do { \ loads them into the full 64-bits registers. */ #define FUNCTION_ARG_PASS_BY_REFERENCE(CUM,MODE,TYPE,NAMED) \ (MUST_PASS_IN_STACK ((MODE), (TYPE)) \ - || SHCOMPACT_BYREF ((CUM), OLD_ARG_MODE ((MODE), (TYPE)), (TYPE), (NAMED))) + || SHCOMPACT_BYREF ((CUM), (MODE), (TYPE), (NAMED))) #define SHCOMPACT_BYREF(CUM, MODE, TYPE, NAMED) \ ((CUM).byref \ -- 2.11.0