* x86-64-tdep.c (x86_64_push_arguments): Always set %rax to number

of SSE registers so that varargs functions work.  Rework handling
	of passing arguments on the stack.
	(x86_64_store_return_value): Return double and float values in SSE
	register.
This commit is contained in:
Andreas Jaeger 2003-06-26 17:08:10 +00:00
parent e8ac10a6d2
commit 8ffd9b1b7a
2 changed files with 193 additions and 142 deletions

View file

@ -1,3 +1,11 @@
2003-06-26 Andreas Jaeger <aj@suse.de>
* x86-64-tdep.c (x86_64_push_arguments): Always set %rax to number
of SSE registers so that varargs functions work. Rework handling
of passing arguments on the stack.
(x86_64_store_return_value): Return double and float values in SSE
register.
2003-06-24 Michael Chastain <mec@shout.net>
* PROBLEMS: Document pr gdb/1091 and pr gdb/1193,

View file

@ -597,7 +597,15 @@ x86_64_push_arguments (struct regcache *regcache, int nargs,
{
int intreg = 0;
int ssereg = 0;
/* For varargs functions we have to pass the total number of SSE arguments
in %rax. So, let's count this number. */
int total_sse_args = 0;
/* Once an SSE/int argument is passed on the stack, all subsequent
arguments are passed there. */
int sse_stack = 0;
int int_stack = 0;
int i;
char buf[8];
static int int_parameter_registers[INT_REGS] =
{
X86_64_RDI_REGNUM, 4, /* %rdi, %rsi */
@ -623,9 +631,7 @@ x86_64_push_arguments (struct regcache *regcache, int nargs,
int needed_sseregs;
if (!n ||
!examine_argument (class, n, &needed_intregs, &needed_sseregs)
|| intreg / 2 + needed_intregs > INT_REGS
|| ssereg / 2 + needed_sseregs > SSE_REGS)
!examine_argument (class, n, &needed_intregs, &needed_sseregs))
{ /* memory class */
stack_values[stack_values_count++] = i;
}
@ -633,6 +639,13 @@ x86_64_push_arguments (struct regcache *regcache, int nargs,
{
int j;
int offset = 0;
if (intreg / 2 + needed_intregs > INT_REGS)
int_stack = 1;
if (ssereg / 2 + needed_sseregs > SSE_REGS)
sse_stack = 1;
total_sse_args += needed_sseregs;
for (j = 0; j < n; j++)
{
switch (class[j])
@ -640,13 +653,21 @@ x86_64_push_arguments (struct regcache *regcache, int nargs,
case X86_64_NO_CLASS:
break;
case X86_64_INTEGER_CLASS:
if (int_stack)
stack_values[stack_values_count++] = i;
else
{
regcache_cooked_write
(regcache, int_parameter_registers[(intreg + 1) / 2],
VALUE_CONTENTS_ALL (args[i]) + offset);
offset += 8;
intreg += 2;
}
break;
case X86_64_INTEGERSI_CLASS:
if (int_stack)
stack_values[stack_values_count++] = i;
else
{
LONGEST val = extract_signed_integer
(VALUE_CONTENTS_ALL (args[i]) + offset, 4);
@ -655,23 +676,33 @@ x86_64_push_arguments (struct regcache *regcache, int nargs,
offset += 8;
intreg++;
break;
}
break;
case X86_64_SSEDF_CLASS:
case X86_64_SSESF_CLASS:
case X86_64_SSE_CLASS:
if (sse_stack)
stack_values[stack_values_count++] = i;
else
{
regcache_cooked_write
(regcache, sse_parameter_registers[(ssereg + 1) / 2],
VALUE_CONTENTS_ALL (args[i]) + offset);
offset += 8;
ssereg += 2;
}
break;
case X86_64_SSEUP_CLASS:
if (sse_stack)
stack_values[stack_values_count++] = i;
else
{
regcache_cooked_write
(regcache, sse_parameter_registers[ssereg / 2],
VALUE_CONTENTS_ALL (args[i]) + offset);
offset += 8;
ssereg++;
}
break;
case X86_64_X87_CLASS:
case X86_64_MEMORY_CLASS:
@ -700,6 +731,11 @@ x86_64_push_arguments (struct regcache *regcache, int nargs,
write_memory (sp, VALUE_CONTENTS_ALL (arg), len);
}
/* Write number of SSE type arguments to RAX to take care of varargs
functions. */
store_unsigned_integer (buf, 8, total_sse_args);
regcache_cooked_write (regcache, X86_64_RAX_REGNUM, buf);
return sp;
}
@ -712,7 +748,8 @@ x86_64_store_return_value (struct type *type, struct regcache *regcache,
{
int len = TYPE_LENGTH (type);
if (TYPE_CODE_FLT == TYPE_CODE (type))
/* First handle long doubles. */
if (TYPE_CODE_FLT == TYPE_CODE (type) && len == 16)
{
ULONGEST fstat;
char buf[FPU_REG_RAW_SIZE];
@ -741,6 +778,12 @@ x86_64_store_return_value (struct type *type, struct regcache *regcache,
for the tag word is 0x3fff. */
regcache_raw_write_unsigned (regcache, FTAG_REGNUM, 0x3fff);
}
else if (TYPE_CODE_FLT == TYPE_CODE (type))
{
/* Handle double and float variables. */
regcache_cooked_write (regcache, X86_64_XMM0_REGNUM, valbuf);
}
/* XXX: What about complex floating point types? */
else
{
int low_size = REGISTER_RAW_SIZE (0);