expr.c (emit_group_load): Revise to allow splitting TCmode source into DImode pieces.

* expr.c (emit_group_load): Revise to allow splitting TCmode source
	into DImode pieces.
	* pa-64.h (LONG_DOUBLE_TYPE_SIZE): Define to 128.
	* pa64-regs.h (CLASS_CANNOT_CHANGE_MODE_P): Inhibit changes from SImode
	for floating-point register class.
	* pa.c (function_arg): Fix handling of modes wider than one word for
	TARGET_64BIT.

From-SVN: r56805
This commit is contained in:
John David Anglin 2002-09-04 18:09:32 +00:00 committed by John David Anglin
parent b10f218708
commit 015b1ad1df
5 changed files with 71 additions and 80 deletions

View File

@ -1,3 +1,14 @@
2002-09-04 John David Anglin <dave@hiauly1.hia.nrc.ca>
* expr.c (emit_group_load): Revise to allow splitting TCmode source
into DImode pieces.
* pa-64.h (LONG_DOUBLE_TYPE_SIZE): Define to 128.
* pa64-regs.h (CLASS_CANNOT_CHANGE_MODE_P): Inhibit changes from SImode
for floating-point register class.
* pa.c (function_arg): Fix handling of modes wider than one word for
TARGET_64BIT.
Wed Sep 4 18:48:10 2002 J"orn Rennecke <joern.rennecke@superh.com>
* combine.c (make_compound_operation): Don't generate zero / sign

View File

@ -65,10 +65,8 @@ Boston, MA 02111-1307, USA. */
#define FLOAT_TYPE_SIZE 32
#undef DOUBLE_TYPE_SIZE
#define DOUBLE_TYPE_SIZE 64
/* This should be 128, but until we work out the ABI for the 128bit
FP codes supplied by HP we'll keep it at 64 bits. */
#undef LONG_DOUBLE_TYPE_SIZE
#define LONG_DOUBLE_TYPE_SIZE 64
#define LONG_DOUBLE_TYPE_SIZE 128
/* Temporary until we figure out what to do with those *(&@$ 32bit
relocs which appear in stabs. */

View File

@ -7446,6 +7446,8 @@ function_arg (cum, mode, type, named, incoming)
int incoming;
{
int max_arg_words = (TARGET_64BIT ? 8 : 4);
int arg_size = FUNCTION_ARG_SIZE (mode, type);
int alignment = 0;
int fpr_reg_base;
int gpr_reg_base;
rtx retval;
@ -7456,16 +7458,15 @@ function_arg (cum, mode, type, named, incoming)
this routine should return zero. FUNCTION_ARG_PARTIAL_NREGS will
handle arguments which are split between regs and stack slots if
the ABI mandates split arguments. */
if (cum->words + FUNCTION_ARG_SIZE (mode, type) > max_arg_words
if (cum->words + arg_size > max_arg_words
|| mode == VOIDmode)
return NULL_RTX;
}
else
{
int offset = 0;
if (FUNCTION_ARG_SIZE (mode, type) > 1 && (cum->words & 1))
offset = 1;
if (cum->words + offset >= max_arg_words
if (arg_size > 1)
alignment = cum->words & 1;
if (cum->words + alignment >= max_arg_words
|| mode == VOIDmode)
return NULL_RTX;
}
@ -7474,70 +7475,54 @@ function_arg (cum, mode, type, named, incoming)
particularly in their handling of FP registers. We might
be able to cleverly share code between them, but I'm not
going to bother in the hope that splitting them up results
in code that is more easily understood.
in code that is more easily understood. */
The 64bit code probably is very wrong for structure passing. */
if (TARGET_64BIT)
{
/* Advance the base registers to their current locations.
Remember, gprs grow towards smaller register numbers while
fprs grow to higher register numbers. Also remember FP regs
are always 4 bytes wide, while the size of an integer register
varies based on the size of the target word. */
fprs grow to higher register numbers. Also remember that
although FP regs are 32-bit addressable, we pretend that
the registers are 64-bits wide. */
gpr_reg_base = 26 - cum->words;
fpr_reg_base = 32 + cum->words;
/* If the argument is more than a word long, then we need to align
the base registers. Same caveats as above. */
if (FUNCTION_ARG_SIZE (mode, type) > 1)
/* Arguments wider than one word need special treatment. */
if (arg_size > 1)
{
if (mode != BLKmode)
{
/* First deal with alignment of the doubleword. */
gpr_reg_base -= (cum->words & 1);
/* Double-extended precision (80-bit), quad-precision (128-bit)
and aggregates including complex numbers are aligned on
128-bit boundaries. The first eight 64-bit argument slots
are associated one-to-one, with general registers r26
through r19, and also with floating-point registers fr4
through fr11. Arguments larger than one word are always
passed in general registers. */
/* This seems backwards, but it is what HP specifies. We need
gpr_reg_base to point to the smaller numbered register of
the integer register pair. So if we have an even register
number, then decrement the gpr base. */
gpr_reg_base -= ((gpr_reg_base % 2) == 0);
rtx loc[8];
int i, offset = 0, ub = arg_size;
/* FP values behave sanely, except that each FP reg is only
half of word. */
fpr_reg_base += ((fpr_reg_base % 2) == 0);
}
else
/* Align the base register. */
gpr_reg_base -= alignment;
ub = MIN (ub, max_arg_words - cum->words - alignment);
for (i = 0; i < ub; i++)
{
rtx loc[8];
int i, offset = 0, ub;
ub = FUNCTION_ARG_SIZE (mode, type);
ub = MIN (ub,
MAX (0, max_arg_words - cum->words - (cum->words & 1)));
gpr_reg_base -= (cum->words & 1);
for (i = 0; i < ub; i++)
{
loc[i] = gen_rtx_EXPR_LIST (VOIDmode,
gen_rtx_REG (DImode,
gpr_reg_base),
GEN_INT (offset));
gpr_reg_base -= 1;
offset += 8;
}
if (ub == 0)
return NULL_RTX;
else if (ub == 1)
return XEXP (loc[0], 0);
else
return gen_rtx_PARALLEL (mode, gen_rtvec_v (ub, loc));
loc[i] = gen_rtx_EXPR_LIST (VOIDmode,
gen_rtx_REG (DImode, gpr_reg_base),
GEN_INT (offset));
gpr_reg_base -= 1;
offset += 8;
}
return gen_rtx_PARALLEL (mode, gen_rtvec_v (ub, loc));
}
}
else
{
/* If the argument is larger than a word, then we know precisely
which registers we must use. */
if (FUNCTION_ARG_SIZE (mode, type) > 1)
if (arg_size > 1)
{
if (cum->words)
{
@ -7559,19 +7544,6 @@ function_arg (cum, mode, type, named, incoming)
}
}
if (TARGET_64BIT && mode == TFmode)
{
return
gen_rtx_PARALLEL
(mode,
gen_rtvec (2,
gen_rtx_EXPR_LIST (VOIDmode,
gen_rtx_REG (DImode, gpr_reg_base + 1),
const0_rtx),
gen_rtx_EXPR_LIST (VOIDmode,
gen_rtx_REG (DImode, gpr_reg_base),
GEN_INT (8))));
}
/* Determine if the argument needs to be passed in both general and
floating point registers. */
if (((TARGET_PORTABLE_RUNTIME || TARGET_64BIT || TARGET_ELF32)

View File

@ -234,16 +234,21 @@ enum reg_class { NO_REGS, R1_REGS, GENERAL_REGS, FPUPPER_REGS, FP_REGS,
/* If defined, gives a class of registers that cannot be used as the
operand of a SUBREG that changes the mode of the object illegally. */
/* ??? This may not actually be necessary anymore. But until I can prove
otherwise it will stay. */
#define CLASS_CANNOT_CHANGE_MODE (FP_REGS)
/* Defines illegal mode changes for CLASS_CANNOT_CHANGE_MODE. */
#define CLASS_CANNOT_CHANGE_MODE_P(FROM,TO) \
(GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO))
/* Defines illegal mode changes for CLASS_CANNOT_CHANGE_MODE.
/* The same information, inverted:
Return the class number of the smallest class containing
SImode loads to floating-point registers are not zero-extended.
The definition for LOAD_EXTEND_OP specifies that integer loads
narrower than BITS_PER_WORD will be zero-extended. As a result,
we inhibit changes from SImode unless they are to a mode that is
identical in size. */
#define CLASS_CANNOT_CHANGE_MODE_P(FROM,TO) \
((FROM) == SImode && GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO))
/* Return the class number of the smallest class containing
reg number REGNO. This could be a conditional expression
or could index an array. */

View File

@ -2265,21 +2265,26 @@ emit_group_load (dst, orig_src, ssize)
}
else if (GET_CODE (src) == CONCAT)
{
if ((bytepos == 0
&& bytelen == GET_MODE_SIZE (GET_MODE (XEXP (src, 0))))
|| (bytepos == (HOST_WIDE_INT) GET_MODE_SIZE (GET_MODE (XEXP (src, 0)))
&& bytelen == GET_MODE_SIZE (GET_MODE (XEXP (src, 1)))))
unsigned int slen = GET_MODE_SIZE (GET_MODE (src));
unsigned int slen0 = GET_MODE_SIZE (GET_MODE (XEXP (src, 0)));
if ((bytepos == 0 && bytelen == slen0)
|| (bytepos != 0 && bytepos + bytelen <= slen))
{
tmps[i] = XEXP (src, bytepos != 0);
/* The following assumes that the concatenated objects all
have the same size. In this case, a simple calculation
can be used to determine the object and the bit field
to be extracted. */
tmps[i] = XEXP (src, bytepos / slen0);
if (! CONSTANT_P (tmps[i])
&& (GET_CODE (tmps[i]) != REG || GET_MODE (tmps[i]) != mode))
tmps[i] = extract_bit_field (tmps[i], bytelen * BITS_PER_UNIT,
0, 1, NULL_RTX, mode, mode, ssize);
(bytepos % slen0) * BITS_PER_UNIT,
1, NULL_RTX, mode, mode, ssize);
}
else if (bytepos == 0)
{
rtx mem = assign_stack_temp (GET_MODE (src),
GET_MODE_SIZE (GET_MODE (src)), 0);
rtx mem = assign_stack_temp (GET_MODE (src), slen, 0);
emit_move_insn (mem, src);
tmps[i] = adjust_address (mem, mode, 0);
}