This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
[RFA] update alpha for push_dummy_call
- From: Richard Henderson <rth at twiddle dot net>
- To: gdb-patches at sources dot redhat dot com
- Date: Sat, 31 May 2003 20:57:32 -0700
- Subject: [RFA] update alpha for push_dummy_call
Ok?
r~
* alpha-tdep.c (alpha_push_dummy_call): Transmography from
alpha_push_arguments. Don't dump argument register data to
the target stack. Fix float and 128-bit long double semantics.
Store $t12 and $ra as specified by the ABI. Use regcache everywhere.
(alpha_fix_call_dummy): Remove.
(alpha_call_dummy_words): Remove.
(alpha_gdbarch_init): Kill deprecated call hooks; add push_dummy_call.
Index: alpha-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/alpha-tdep.c,v
retrieving revision 1.88
diff -c -p -d -r1.88 alpha-tdep.c
*** alpha-tdep.c 31 May 2003 00:27:45 -0000 1.88
--- alpha-tdep.c 1 Jun 2003 03:39:04 -0000
*************** alpha_register_convert_to_raw (struct ty
*** 173,210 ****
/* The alpha passes the first six arguments in the registers, the rest on
! the stack. The register arguments are eventually transferred to the
! argument transfer area immediately below the stack by the called function
! anyway. So we `push' at least six arguments on the stack, `reload' the
! argument registers and then adjust the stack pointer to point past the
! sixth argument. This algorithm simplifies the passing of a large struct
! which extends from the registers to the stack.
If the called function is returning a structure, the address of the
structure to be returned is passed as a hidden first argument. */
static CORE_ADDR
! alpha_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
! int struct_return, CORE_ADDR struct_addr)
{
int i;
int accumulate_size = struct_return ? 8 : 0;
- int arg_regs_size = ALPHA_NUM_ARG_REGS * 8;
struct alpha_arg
{
char *contents;
int len;
int offset;
};
! struct alpha_arg *alpha_args =
! (struct alpha_arg *) alloca (nargs * sizeof (struct alpha_arg));
register struct alpha_arg *m_arg;
! char raw_buffer[ALPHA_REGISTER_BYTES];
int required_arg_regs;
for (i = 0, m_arg = alpha_args; i < nargs; i++, m_arg++)
{
struct value *arg = args[i];
struct type *arg_type = check_typedef (VALUE_TYPE (arg));
/* Cast argument to long if necessary as the compiler does it too. */
switch (TYPE_CODE (arg_type))
{
--- 173,222 ----
/* The alpha passes the first six arguments in the registers, the rest on
! the stack. The register arguments are stored in ARG_REG_BUFFER, and
! then moved into the register file; this simplifies the passing of a
! large struct which extends from the registers to the stack, plus avoids
! three ptrace invocations per word.
!
! We don't bother tracking which register values should go in integer
! regs or fp regs; we load the same values into both.
!
If the called function is returning a structure, the address of the
structure to be returned is passed as a hidden first argument. */
static CORE_ADDR
! alpha_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
! struct regcache *regcache, CORE_ADDR bp_addr,
! int nargs, struct value **args, CORE_ADDR sp,
! int struct_return, CORE_ADDR struct_addr)
{
int i;
int accumulate_size = struct_return ? 8 : 0;
struct alpha_arg
{
char *contents;
int len;
int offset;
};
! struct alpha_arg *alpha_args
! = (struct alpha_arg *) alloca (nargs * sizeof (struct alpha_arg));
register struct alpha_arg *m_arg;
! char arg_reg_buffer[ALPHA_REGISTER_SIZE * ALPHA_NUM_ARG_REGS];
int required_arg_regs;
+ /* The ABI places the address of the called function in T12. */
+ regcache_cooked_write_signed (regcache, ALPHA_T12_REGNUM, func_addr);
+
+ /* Set the return address register to point to the entry point
+ of the program, where a breakpoint lies in wait. */
+ regcache_cooked_write_signed (regcache, ALPHA_RA_REGNUM, bp_addr);
+
+ /* Lay out the arguments in memory. */
for (i = 0, m_arg = alpha_args; i < nargs; i++, m_arg++)
{
struct value *arg = args[i];
struct type *arg_type = check_typedef (VALUE_TYPE (arg));
+
/* Cast argument to long if necessary as the compiler does it too. */
switch (TYPE_CODE (arg_type))
{
*************** alpha_push_arguments (int nargs, struct
*** 219,224 ****
--- 231,260 ----
arg = value_cast (arg_type, arg);
}
break;
+ case TYPE_CODE_FLT:
+ /* "float" arguments loaded in registers must be passed in
+ register format, aka "double". */
+ if (accumulate_size < sizeof (arg_reg_buffer)
+ && TYPE_LENGTH (arg_type) == 4)
+ {
+ arg_type = builtin_type_double;
+ arg = value_cast (arg_type, arg);
+ }
+ /* Tru64 5.1 has a 128-bit long double, and passes this by
+ invisible reference. No one else uses this data type. */
+ else if (TYPE_LENGTH (arg_type) == 16)
+ {
+ /* Allocate aligned storage. */
+ sp = (sp & -16) - 16;
+
+ /* Write the real data into the stack. */
+ write_memory (sp, VALUE_CONTENTS (arg), 16);
+
+ /* Construct the indirection. */
+ arg_type = lookup_pointer_type (arg_type);
+ arg = value_from_pointer (arg_type, sp);
+ }
+ break;
default:
break;
}
*************** alpha_push_arguments (int nargs, struct
*** 235,267 ****
required_arg_regs = ALPHA_NUM_ARG_REGS;
/* Make room for the arguments on the stack. */
! if (accumulate_size < arg_regs_size)
! accumulate_size = arg_regs_size;
sp -= accumulate_size;
! /* Keep sp aligned to a multiple of 16 as the compiler does it too. */
sp &= ~15;
/* `Push' arguments on the stack. */
for (i = nargs; m_arg--, --i >= 0;)
- write_memory (sp + m_arg->offset, m_arg->contents, m_arg->len);
- if (struct_return)
{
! store_unsigned_integer (raw_buffer, ALPHA_REGISTER_BYTES, struct_addr);
! write_memory (sp, raw_buffer, ALPHA_REGISTER_BYTES);
}
/* Load the argument registers. */
for (i = 0; i < required_arg_regs; i++)
{
LONGEST val;
! val = read_memory_integer (sp + i * 8, ALPHA_REGISTER_BYTES);
! write_register (ALPHA_A0_REGNUM + i, val);
! write_register (ALPHA_FPA0_REGNUM + i, val);
}
! return sp + arg_regs_size;
}
/* Given a return value in `regbuf' with a type `valtype',
--- 271,328 ----
required_arg_regs = ALPHA_NUM_ARG_REGS;
/* Make room for the arguments on the stack. */
! if (accumulate_size < sizeof(arg_reg_buffer))
! accumulate_size = 0;
! else
! accumulate_size -= sizeof(arg_reg_buffer);
sp -= accumulate_size;
! /* Keep sp aligned to a multiple of 16 as the ABI requires. */
sp &= ~15;
/* `Push' arguments on the stack. */
for (i = nargs; m_arg--, --i >= 0;)
{
! char *contents = m_arg->contents;
! int offset = m_arg->offset;
! int len = m_arg->len;
!
! /* Copy the bytes destined for registers into arg_reg_buffer. */
! if (offset < sizeof(arg_reg_buffer))
! {
! if (offset + len <= sizeof(arg_reg_buffer))
! {
! memcpy (arg_reg_buffer + offset, contents, len);
! continue;
! }
! else
! {
! int tlen = sizeof(arg_reg_buffer) - offset;
! memcpy (arg_reg_buffer + offset, contents, tlen);
! offset += tlen;
! contents += tlen;
! len -= tlen;
! }
! }
!
! /* Everything else goes to the stack. */
! write_memory (sp + offset - sizeof(arg_reg_buffer), contents, len);
}
+ if (struct_return)
+ store_unsigned_integer (arg_reg_buffer, ALPHA_REGISTER_SIZE, struct_addr);
/* Load the argument registers. */
for (i = 0; i < required_arg_regs; i++)
{
LONGEST val;
! val = extract_unsigned_integer (arg_reg_buffer + i*ALPHA_REGISTER_SIZE,
! ALPHA_REGISTER_SIZE);
! regcache_cooked_write_signed (regcache, ALPHA_A0_REGNUM + i, val);
! regcache_cooked_write_signed (regcache, ALPHA_FPA0_REGNUM + i, val);
}
! return sp;
}
/* Given a return value in `regbuf' with a type `valtype',
*************** alpha_skip_prologue (CORE_ADDR pc)
*** 438,465 ****
}
- /* Construct an inferior call to FUN. For Alpha this is as simple as
- initializing the RA and T12 registers; everything else is set up by
- generic code. */
-
- static void
- alpha_fix_call_dummy (char *dummy, CORE_ADDR pc, CORE_ADDR fun, int nargs,
- struct value **args, struct type *type, int gcc_p)
- {
- CORE_ADDR bp_address = CALL_DUMMY_ADDRESS ();
-
- if (bp_address == 0)
- error ("no place to put call");
- write_register (ALPHA_RA_REGNUM, bp_address);
- write_register (ALPHA_T12_REGNUM, fun);
- }
-
- /* On the Alpha, the call dummy code is never copied to user space
- (see alpha_fix_call_dummy() above). The contents of this do not
- matter. */
- LONGEST alpha_call_dummy_words[] = { 0 };
-
-
/* Figure out where the longjmp will land.
We expect the first arg to be a pointer to the jmp_buf structure from
which we extract the PC (JB_PC) that we will land at. The PC is copied
--- 499,504 ----
*************** alpha_gdbarch_init (struct gdbarch_info
*** 1242,1252 ****
alpha_extract_struct_value_address);
/* Settings for calling functions in the inferior. */
! set_gdbarch_deprecated_push_arguments (gdbarch, alpha_push_arguments);
! set_gdbarch_deprecated_call_dummy_words (gdbarch, alpha_call_dummy_words);
! set_gdbarch_deprecated_sizeof_call_dummy_words (gdbarch, 0);
! set_gdbarch_deprecated_pc_in_call_dummy (gdbarch, deprecated_pc_in_call_dummy_at_entry_point);
! set_gdbarch_deprecated_fix_call_dummy (gdbarch, alpha_fix_call_dummy);
/* Methods for saving / extracting a dummy frame's ID. */
set_gdbarch_unwind_dummy_id (gdbarch, alpha_unwind_dummy_id);
--- 1281,1287 ----
alpha_extract_struct_value_address);
/* Settings for calling functions in the inferior. */
! set_gdbarch_push_dummy_call (gdbarch, alpha_push_dummy_call);
/* Methods for saving / extracting a dummy frame's ID. */
set_gdbarch_unwind_dummy_id (gdbarch, alpha_unwind_dummy_id);