Back out these patches:
2003-06-02 J"orn Rennecke <joern.rennecke@superh.com> * 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 <joern.rennecke@superh.com> * 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. From-SVN: r68430
This commit is contained in:
parent
d28dd0f9d1
commit
6d1cb95f3f
@ -1,3 +1,24 @@
|
||||
2003-06-24 J"orn Rennecke <joern.rennecke@superh.com>
|
||||
|
||||
Back out these patches:
|
||||
2003-06-02 J"orn Rennecke <joern.rennecke@superh.com>
|
||||
* 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 <joern.rennecke@superh.com>
|
||||
* 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 <falk.hueffner@student.uni-tuebingen.de>
|
||||
|
||||
PR target/11260
|
||||
|
@ -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
|
||||
|
@ -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 \
|
||||
|
Loading…
Reference in New Issue
Block a user