+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.
+
2003-06-30 Andreas Schwab <schwab@suse.de>
* utils.c (internal_vproblem): Use xvasprintf, not xasprintf, to
#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_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
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
+ corresponding union types are handled normally.) So we include
those types here. *shrug* */
static int
is_float_like (struct type *type)
}
+/* 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
/* 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)
+ return ((is_integer_like (type) && length <= DEPRECATED_REGISTER_SIZE)
|| is_pointer_like (type)
- || (is_struct_like (type) && length != 8)
- || (is_float_like (type) && length == 16));
+ || (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'. */
{
unsigned length = TYPE_LENGTH (type);
- return ((is_struct_like (type) && length != 1 && length != 2 && length != 4)
- || (is_float_like (type) && length == 16));
+ return (is_struct_like (type)
+ && !(is_power_of_two (length) && length <= DEPRECATED_REGISTER_SIZE));
}
}
-/* 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
sp = round_down (sp, alignment_of (type));
- /* SIMPLE_ARG values get extended to 32 bits. Assume every
- argument is. */
- if (length < 4) length = 4;
+ /* 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;
}
}
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 <= 2)
+ && fr <= S390_NUM_FP_PARAMETER_REGISTERS * 2 - 2)
{
/* When we store a single-precision value in an FP register,
it occupies the leftmost bits. */
deprecated_write_register_gen (S390_GP0_REGNUM + gr,
VALUE_CONTENTS (arg));
deprecated_write_register_gen (S390_GP0_REGNUM + gr + 1,
- VALUE_CONTENTS (arg) + 4);
+ VALUE_CONTENTS (arg) + DEPRECATED_REGISTER_SIZE);
gr += 2;
}
else
if (is_simple_arg (type))
{
- /* Simple args are always either extended to 32 bits,
- or pointers. */
- starg = round_up (starg, 4);
+ /* 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? */
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,
+ /* Simple args are always extended to
+ DEPRECATED_REGISTER_SIZE bytes. */
+ write_memory_signed_integer (starg, DEPRECATED_REGISTER_SIZE,
extend_simple_arg (arg));
- starg += 4;
+ 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-byte boundary, even when passing doubles. */
- starg = round_up (starg, 4);
+ 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;
}
/* 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;
+ 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