* i386-tdep.c (i386_16_byte_align_p): New.

(i386_push_dummy_call): Determine stack space required for
	arguments going forwards allowing for 16-byte alignment, then push
	arguments going forwards.
This commit is contained in:
Joseph Myers
2008-06-27 16:22:56 +00:00
parent db42f21025
commit 7ccc1c74d8
2 changed files with 91 additions and 17 deletions

View File

@ -1,3 +1,10 @@
2008-06-27 Joseph Myers <joseph@codesourcery.com>
* i386-tdep.c (i386_16_byte_align_p): New.
(i386_push_dummy_call): Determine stack space required for
arguments going forwards allowing for 16-byte alignment, then push
arguments going forwards.
2008-06-27 Pedro Alves <pedro@codesourcery.com> 2008-06-27 Pedro Alves <pedro@codesourcery.com>
* infrun.c (start_remote): Don't clear thread list here. * infrun.c (start_remote): Don't clear thread list here.

View File

@ -1521,6 +1521,34 @@ i386_get_longjmp_target (struct frame_info *frame, CORE_ADDR *pc)
} }
/* Check whether TYPE must be 16-byte-aligned when passed as a
function argument. 16-byte vectors, _Decimal128 and structures or
unions containing such types must be 16-byte-aligned; other
arguments are 4-byte-aligned. */
static int
i386_16_byte_align_p (struct type *type)
{
type = check_typedef (type);
if ((TYPE_CODE (type) == TYPE_CODE_DECFLOAT
|| (TYPE_CODE (type) == TYPE_CODE_ARRAY && TYPE_VECTOR (type)))
&& TYPE_LENGTH (type) == 16)
return 1;
if (TYPE_CODE (type) == TYPE_CODE_ARRAY)
return i386_16_byte_align_p (TYPE_TARGET_TYPE (type));
if (TYPE_CODE (type) == TYPE_CODE_STRUCT
|| TYPE_CODE (type) == TYPE_CODE_UNION)
{
int i;
for (i = 0; i < TYPE_NFIELDS (type); i++)
{
if (i386_16_byte_align_p (TYPE_FIELD_TYPE (type, i)))
return 1;
}
}
return 0;
}
static CORE_ADDR static CORE_ADDR
i386_push_dummy_call (struct gdbarch *gdbarch, struct value *function, i386_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
struct regcache *regcache, CORE_ADDR bp_addr, int nargs, struct regcache *regcache, CORE_ADDR bp_addr, int nargs,
@ -1529,12 +1557,42 @@ i386_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
{ {
gdb_byte buf[4]; gdb_byte buf[4];
int i; int i;
int write_pass;
int args_space = 0;
/* Push arguments in reverse order. */ /* Determine the total space required for arguments and struct
for (i = nargs - 1; i >= 0; i--) return address in a first pass (allowing for 16-byte-aligned
arguments), then push arguments in a second pass. */
for (write_pass = 0; write_pass < 2; write_pass++)
{
int args_space_used = 0;
int have_16_byte_aligned_arg = 0;
if (struct_return)
{
if (write_pass)
{
/* Push value address. */
store_unsigned_integer (buf, 4, struct_addr);
write_memory (sp, buf, 4);
args_space_used += 4;
}
else
args_space += 4;
}
for (i = 0; i < nargs; i++)
{ {
int len = TYPE_LENGTH (value_enclosing_type (args[i])); int len = TYPE_LENGTH (value_enclosing_type (args[i]));
if (write_pass)
{
if (i386_16_byte_align_p (value_enclosing_type (args[i])))
args_space_used = align_up (args_space_used, 16);
write_memory (sp + args_space_used,
value_contents_all (args[i]), len);
/* The System V ABI says that: /* The System V ABI says that:
"An argument's size is increased, if necessary, to make it a "An argument's size is increased, if necessary, to make it a
@ -1542,16 +1600,25 @@ i386_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
depending on the size of the argument." depending on the size of the argument."
This makes sure the stack stays word-aligned. */ This makes sure the stack stays word-aligned. */
sp -= (len + 3) & ~3; args_space_used += align_up (len, 4);
write_memory (sp, value_contents_all (args[i]), len); }
else
{
if (i386_16_byte_align_p (value_enclosing_type (args[i])))
{
args_space = align_up (args_space, 16);
have_16_byte_aligned_arg = 1;
}
args_space += align_up (len, 4);
}
} }
/* Push value address. */ if (!write_pass)
if (struct_return)
{ {
sp -= 4; if (have_16_byte_aligned_arg)
store_unsigned_integer (buf, 4, struct_addr); args_space = align_up (args_space, 16);
write_memory (sp, buf, 4); sp -= args_space;
}
} }
/* Store return address. */ /* Store return address. */