* [patch]: fix argument passing on S/390 and S/390x
@ 2003-07-01 0:06 Jim Blandy
2003-07-01 0:14 ` Jim Blandy
0 siblings, 1 reply; 2+ messages in thread
From: Jim Blandy @ 2003-07-01 0:06 UTC (permalink / raw)
To: gdb-patches
This is a patch that was discussed and approved long ago; only
recently has the legal paperwork finally come through.
2003-06-30 Jim Blandy <jimb@redhat.com>
Patch from IBM (authors unspecified, probably Ulrich Weigand and
Gerhard Tonn) for argument passing on the S/390 and S/390x:
* s390-tdep.c (S390_STACK_FRAME_OVERHEAD): This is always space
for 16 registers, and then 32 more bytes.
(S390_STACK_PARAMETER_ALIGNMENT, S390_NUM_FP_PARAMETER_REGISTERS):
New macros.
(is_double_arg): The s390x doesn't handle DOUBLE_ARGS specially.
Move up in the file, since it's now used by is_simple_arg.
(is_simple_arg): Don't assume registers are four bytes long.
Exclude all double arguments. Extended floats are not simple
args.
(is_power_of_two): New function.
(pass_by_copy_ref): Call is_power_of_two, and check that the
length fits in a register, rather than listing all the acceptable
sizes. Extended floats are not passed by reference.
(s390_push_arguments): Don't assume registers are four bytes long.
Reserve an argument register to point to the buffer for structures
returned by value. Use S390_NUM_FP_PARAMETER_REGISTERS and
S390_STACK_FRAME_OVERHEAD.
Index: gdb/s390-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/s390-tdep.c,v
retrieving revision 1.105
diff -c -r1.105 s390-tdep.c
*** gdb/s390-tdep.c 20 Jun 2003 13:57:28 -0000 1.105
--- gdb/s390-tdep.c 1 Jul 2003 00:04:28 -0000
***************
*** 93,99 ****
#define S390X_SIGREGS_FP0_OFFSET (216)
#define S390_UC_MCONTEXT_OFFSET (256)
#define S390X_UC_MCONTEXT_OFFSET (344)
! #define S390_STACK_FRAME_OVERHEAD (GDB_TARGET_IS_ESAME ? 160:96)
#define S390_SIGNAL_FRAMESIZE (GDB_TARGET_IS_ESAME ? 160:96)
#define s390_NR_sigreturn 119
#define s390_NR_rt_sigreturn 173
--- 93,101 ----
#define S390X_SIGREGS_FP0_OFFSET (216)
#define S390_UC_MCONTEXT_OFFSET (256)
#define S390X_UC_MCONTEXT_OFFSET (344)
! #define S390_STACK_FRAME_OVERHEAD 16*DEPRECATED_REGISTER_SIZE+32
! #define S390_STACK_PARAMETER_ALIGNMENT DEPRECATED_REGISTER_SIZE
! #define S390_NUM_FP_PARAMETER_REGISTERS (GDB_TARGET_IS_ESAME ? 4:2)
#define S390_SIGNAL_FRAMESIZE (GDB_TARGET_IS_ESAME ? 160:96)
#define s390_NR_sigreturn 119
#define s390_NR_rt_sigreturn 173
***************
*** 1331,1337 ****
You'd think this would just be floats, doubles, long doubles, etc.
But as an odd quirk, not mentioned in the ABI, GCC passes float and
double singletons as if they were a plain float, double, etc. (The
! corresponding union types are handled normally.) So we exclude
those types here. *shrug* */
static int
is_float_like (struct type *type)
--- 1333,1339 ----
You'd think this would just be floats, doubles, long doubles, etc.
But as an odd quirk, not mentioned in the ABI, GCC passes float and
double singletons as if they were a plain float, double, etc. (The
! corresponding union types are handled normally.) So we include
those types here. *shrug* */
static int
is_float_like (struct type *type)
***************
*** 1354,1359 ****
--- 1356,1380 ----
}
+ /* Return non-zero if TYPE is a `DOUBLE_ARG', as defined by the
+ parameter passing conventions described in the "GNU/Linux for S/390
+ ELF Application Binary Interface Supplement". Return zero
+ otherwise. */
+ static int
+ is_double_arg (struct type *type)
+ {
+ unsigned length = TYPE_LENGTH (type);
+
+ /* The s390x ABI doesn't handle DOUBLE_ARGS specially. */
+ if (GDB_TARGET_IS_ESAME)
+ return 0;
+
+ return ((is_integer_like (type)
+ || is_struct_like (type))
+ && length == 8);
+ }
+
+
/* Return non-zero if TYPE is considered a `SIMPLE_ARG', as defined by
the parameter passing conventions described in the "GNU/Linux for
S/390 ELF Application Binary Interface Supplement". Return zero
***************
*** 1365,1377 ****
/* This is almost a direct translation of the ABI's language, except
that we have to exclude 8-byte structs; those are DOUBLE_ARGs. */
! return ((is_integer_like (type) && length <= 4)
|| is_pointer_like (type)
! || (is_struct_like (type) && length != 8)
! || (is_float_like (type) && length == 16));
}
/* Return non-zero if TYPE should be passed as a pointer to a copy,
zero otherwise. TYPE must be a SIMPLE_ARG, as recognized by
`is_simple_arg'. */
--- 1386,1403 ----
/* This is almost a direct translation of the ABI's language, except
that we have to exclude 8-byte structs; those are DOUBLE_ARGs. */
! return ((is_integer_like (type) && length <= DEPRECATED_REGISTER_SIZE)
|| is_pointer_like (type)
! || (is_struct_like (type) && !is_double_arg (type)));
}
+ static int
+ is_power_of_two (unsigned int n)
+ {
+ return ((n & (n - 1)) == 0);
+ }
+
/* Return non-zero if TYPE should be passed as a pointer to a copy,
zero otherwise. TYPE must be a SIMPLE_ARG, as recognized by
`is_simple_arg'. */
***************
*** 1380,1387 ****
{
unsigned length = TYPE_LENGTH (type);
! return ((is_struct_like (type) && length != 1 && length != 2 && length != 4)
! || (is_float_like (type) && length == 16));
}
--- 1406,1413 ----
{
unsigned length = TYPE_LENGTH (type);
! return (is_struct_like (type)
! && !(is_power_of_two (length) && length <= DEPRECATED_REGISTER_SIZE));
}
***************
*** 1404,1424 ****
}
- /* Return non-zero if TYPE is a `DOUBLE_ARG', as defined by the
- parameter passing conventions described in the "GNU/Linux for S/390
- ELF Application Binary Interface Supplement". Return zero
- otherwise. */
- static int
- is_double_arg (struct type *type)
- {
- unsigned length = TYPE_LENGTH (type);
-
- return ((is_integer_like (type)
- || is_struct_like (type))
- && length == 8);
- }
-
-
/* Round ADDR up to the next N-byte boundary. N must be a power of
two. */
static CORE_ADDR
--- 1430,1435 ----
***************
*** 1538,1546 ****
sp = round_down (sp, alignment_of (type));
! /* SIMPLE_ARG values get extended to 32 bits. Assume every
! argument is. */
! if (length < 4) length = 4;
sp -= length;
}
}
--- 1549,1557 ----
sp = round_down (sp, alignment_of (type));
! /* SIMPLE_ARG values get extended to DEPRECATED_REGISTER_SIZE bytes.
! Assume every argument is. */
! if (length < DEPRECATED_REGISTER_SIZE) length = DEPRECATED_REGISTER_SIZE;
sp -= length;
}
}
***************
*** 1561,1573 ****
int gr = 2;
CORE_ADDR starg = sp;
for (i = 0; i < nargs; i++)
{
struct value *arg = args[i];
struct type *type = VALUE_TYPE (arg);
if (is_double_or_float (type)
! && fr <= 2)
{
/* When we store a single-precision value in an FP register,
it occupies the leftmost bits. */
--- 1572,1588 ----
int gr = 2;
CORE_ADDR starg = sp;
+ /* A struct is returned using general register 2 */
+ if (struct_return)
+ gr++;
+
for (i = 0; i < nargs; i++)
{
struct value *arg = args[i];
struct type *type = VALUE_TYPE (arg);
if (is_double_or_float (type)
! && fr <= S390_NUM_FP_PARAMETER_REGISTERS * 2 - 2)
{
/* When we store a single-precision value in an FP register,
it occupies the leftmost bits. */
***************
*** 1594,1600 ****
deprecated_write_register_gen (S390_GP0_REGNUM + gr,
VALUE_CONTENTS (arg));
deprecated_write_register_gen (S390_GP0_REGNUM + gr + 1,
! VALUE_CONTENTS (arg) + 4);
gr += 2;
}
else
--- 1609,1615 ----
deprecated_write_register_gen (S390_GP0_REGNUM + gr,
VALUE_CONTENTS (arg));
deprecated_write_register_gen (S390_GP0_REGNUM + gr + 1,
! VALUE_CONTENTS (arg) + DEPRECATED_REGISTER_SIZE);
gr += 2;
}
else
***************
*** 1610,1618 ****
if (is_simple_arg (type))
{
! /* Simple args are always either extended to 32 bits,
! or pointers. */
! starg = round_up (starg, 4);
/* Do we need to pass a pointer to our copy of this
argument? */
--- 1625,1633 ----
if (is_simple_arg (type))
{
! /* Simple args are always extended to
! DEPRECATED_REGISTER_SIZE bytes. */
! starg = round_up (starg, DEPRECATED_REGISTER_SIZE);
/* Do we need to pass a pointer to our copy of this
argument? */
***************
*** 1620,1637 ****
write_memory_signed_integer (starg, pointer_size,
copy_addr[i]);
else
! /* Simple args are always extended to 32 bits. */
! write_memory_signed_integer (starg, 4,
extend_simple_arg (arg));
! starg += 4;
}
else
{
/* You'd think we should say:
starg = round_up (starg, alignment_of (type));
Unfortunately, GCC seems to simply align the stack on
! a four-byte boundary, even when passing doubles. */
! starg = round_up (starg, 4);
write_memory (starg, VALUE_CONTENTS (arg), length);
starg += length;
}
--- 1635,1653 ----
write_memory_signed_integer (starg, pointer_size,
copy_addr[i]);
else
! /* Simple args are always extended to
! DEPRECATED_REGISTER_SIZE bytes. */
! write_memory_signed_integer (starg, DEPRECATED_REGISTER_SIZE,
extend_simple_arg (arg));
! starg += DEPRECATED_REGISTER_SIZE;
}
else
{
/* You'd think we should say:
starg = round_up (starg, alignment_of (type));
Unfortunately, GCC seems to simply align the stack on
! a four/eight-byte boundary, even when passing doubles. */
! starg = round_up (starg, S390_STACK_PARAMETER_ALIGNMENT);
write_memory (starg, VALUE_CONTENTS (arg), length);
starg += length;
}
***************
*** 1642,1648 ****
/* Allocate the standard frame areas: the register save area, the
word reserved for the compiler (which seems kind of meaningless),
and the back chain pointer. */
! sp -= 96;
/* Write the back chain pointer into the first word of the stack
frame. This will help us get backtraces from within functions
--- 1658,1664 ----
/* Allocate the standard frame areas: the register save area, the
word reserved for the compiler (which seems kind of meaningless),
and the back chain pointer. */
! sp -= S390_STACK_FRAME_OVERHEAD;
/* Write the back chain pointer into the first word of the stack
frame. This will help us get backtraces from within functions
^ permalink raw reply [flat|nested] 2+ messages in thread* Re: [patch]: fix argument passing on S/390 and S/390x
2003-07-01 0:06 [patch]: fix argument passing on S/390 and S/390x Jim Blandy
@ 2003-07-01 0:14 ` Jim Blandy
0 siblings, 0 replies; 2+ messages in thread
From: Jim Blandy @ 2003-07-01 0:14 UTC (permalink / raw)
To: gdb-patches
I've committed this to the 6.0 release branch, too.
Jim Blandy <jimb@redhat.com> writes:
> This is a patch that was discussed and approved long ago; only
> recently has the legal paperwork finally come through.
>
> 2003-06-30 Jim Blandy <jimb@redhat.com>
>
> Patch from IBM (authors unspecified, probably Ulrich Weigand and
> Gerhard Tonn) for argument passing on the S/390 and S/390x:
> * s390-tdep.c (S390_STACK_FRAME_OVERHEAD): This is always space
> for 16 registers, and then 32 more bytes.
> (S390_STACK_PARAMETER_ALIGNMENT, S390_NUM_FP_PARAMETER_REGISTERS):
> New macros.
> (is_double_arg): The s390x doesn't handle DOUBLE_ARGS specially.
> Move up in the file, since it's now used by is_simple_arg.
> (is_simple_arg): Don't assume registers are four bytes long.
> Exclude all double arguments. Extended floats are not simple
> args.
> (is_power_of_two): New function.
> (pass_by_copy_ref): Call is_power_of_two, and check that the
> length fits in a register, rather than listing all the acceptable
> sizes. Extended floats are not passed by reference.
> (s390_push_arguments): Don't assume registers are four bytes long.
> Reserve an argument register to point to the buffer for structures
> returned by value. Use S390_NUM_FP_PARAMETER_REGISTERS and
> S390_STACK_FRAME_OVERHEAD.
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2003-07-01 0:14 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-07-01 0:06 [patch]: fix argument passing on S/390 and S/390x Jim Blandy
2003-07-01 0:14 ` Jim Blandy
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox