* [m68k] fix return value extraction
@ 2006-06-05 15:26 Nathan Sidwell
2006-06-05 16:51 ` Andreas Schwab
2006-06-09 10:13 ` Andreas Schwab
0 siblings, 2 replies; 8+ messages in thread
From: Nathan Sidwell @ 2006-06-05 15:26 UTC (permalink / raw)
To: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 1207 bytes --]
I discovered gdb's idea of how values are returned differed significantly from
how gcc actually returned things. Although gcc might be at variance from the
ABI specification, I didn't want to change gcc's behaviour and thereby introduce
ABI incompatibilities there. AFAICT gcc's behaviour has been unchanged for a while.
*) GCC passes smalls structs that have an integral mode in a register, not small
structs per se. It is annoying that an implementation detail of gcc's internals
is affecting the ABI this way. I've reproduced what I think is an equivalent
algorithm, so gdb can determine this.
*) GCC never sets %a0 to point to a returned structure. Neither does it return
pointer values in %a0.
*) coldfire chips really need the stack to be aligned to a 4 byte boundary.
*) In order for bare metal elf to work, I've defaulted gdb's configuration to be
that, and added an os initialization routine for a.out.
*) I've enabled the linux sniffers for a uclinux target.
tested on a coldfire target board bare metal.
ok?
nathan
--
Nathan Sidwell :: http://www.codesourcery.com :: CodeSourcery
nathan@codesourcery.com :: http://www.planetfall.pwp.blueyonder.co.uk
[-- Attachment #2: call-ret.patch --]
[-- Type: text/x-patch, Size: 12623 bytes --]
2006-06-05 Nathan Sidwell <nathan@codesourcery.com>
* gdb/configure.tgt (gdb_osabi): uclinux is like linux.
* gdb/m68k-tdep.c (m68k_svr4_extract_return_value): Return value
is never in %a0.
(m68k_reg_struct_return_p): Duplicate gcc's struct mode algorithm.
(m68k_svr4_return_value) Use VALUE_STRUCT_CONVENTION. do not rely
on %a0.
(m68k_push_dummy_call): Force stack alignment.
(m68k_svr4_init_abi): Set struct_return convention.
(m68k_aout_init_abi): New.
(m68k_gdbarch_init): Default to bare elf ABI that gcc provides.
* gdb/m68k-tdep.h (m68k_aout_init_abi): Declare.
* gdb/m68kbsd-tdep.c (m68kbsd_aout_init_abi): Use m68k_aout_init_abi.
(m68kbsd_elf_init_abi): Add comment.
* gdb/m68klinux-tdep.c (m68k_linux_init_abi): Just set the struct
pointer register here.
Index: configure.tgt
===================================================================
RCS file: /cvs/src/src/gdb/configure.tgt,v
retrieving revision 1.172
diff -c -3 -p -r1.172 configure.tgt
*** configure.tgt 20 Apr 2006 23:18:48 -0000 1.172
--- configure.tgt 5 Jun 2006 15:16:55 -0000
*************** esac
*** 223,228 ****
--- 223,229 ----
case "${target}" in
*-*-freebsd*) gdb_osabi=GDB_OSABI_FREEBSD_ELF ;;
*-*-linux*) gdb_osabi=GDB_OSABI_LINUX ;;
+ *-*-uclinux*) gdb_osabi=GDB_OSABI_LINUX ;;
*-*-nto*) gdb_osabi=GDB_OSABI_QNXNTO ;;
m68*-*-openbsd* | m88*-*-openbsd* | vax-*-openbsd*) ;;
*-*-openbsd*) gdb_osabi=GDB_OSABI_OPENBSD_ELF ;;
Index: m68k-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/m68k-tdep.c,v
retrieving revision 1.105
diff -c -3 -p -r1.105 m68k-tdep.c
*** m68k-tdep.c 17 Dec 2005 22:34:01 -0000 1.105
--- m68k-tdep.c 5 Jun 2006 15:16:56 -0000
*************** m68k_svr4_extract_return_value (struct t
*** 252,259 ****
--- 252,262 ----
regcache_raw_read (regcache, M68K_FP0_REGNUM, buf);
convert_typed_floating (buf, builtin_type_m68881_ext, valbuf, type);
}
+ #if 0
+ /* GCC never differentiates pointer return types this way. */
else if (TYPE_CODE (type) == TYPE_CODE_PTR && len == 4)
regcache_raw_read (regcache, M68K_A0_REGNUM, valbuf);
+ #endif
else
m68k_extract_return_value (type, regcache, valbuf);
}
*************** m68k_reg_struct_return_p (struct gdbarch
*** 310,322 ****
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
enum type_code code = TYPE_CODE (type);
int len = TYPE_LENGTH (type);
gdb_assert (code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION);
if (tdep->struct_return == pcc_struct_return)
return 0;
! return (len == 1 || len == 2 || len == 4 || len == 8);
}
/* Determine, for architecture GDBARCH, how a return value of TYPE
--- 313,409 ----
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
enum type_code code = TYPE_CODE (type);
int len = TYPE_LENGTH (type);
+ int align;
+ int ix;
+ struct type *union_field_type = NULL;
gdb_assert (code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION);
if (tdep->struct_return == pcc_struct_return)
return 0;
! /* Unfortunately GCC incorrectly implements this optimization.
! Rather than simply return all small structs, or even just those
! of size 2^N, it uses the mode of the structure to determine this.
! BLKmode structs will be returned by memory and QI,HI,SI,DI,SF&DF
! mode structs will be returned by register. For m68k a struct is
! BLKmode unless it's size is 2^N and the mode for that size does
! not need a greater alignment than the structure itself. Unions
! will get the mode of last member whose size matches that of the
! union itself. This is horrible. */
!
! if (len > 8 || (len & -len) != len)
! /* Length is not 2^n or is too big. */
! return 0;
!
! align = len > 4 ? 4 : len;
! for (ix = 0; ix != TYPE_NFIELDS (type); ix++)
! {
! struct type *field_type;
! int field_len;
!
! if (TYPE_FIELD_STATIC (type, ix))
! /* Skip static fields. */
! continue;
!
! field_type = TYPE_FIELD_TYPE (type, ix);
! field_type = check_typedef (field_type);
! field_len = TYPE_LENGTH (field_type);
!
! if (code == TYPE_CODE_STRUCT)
! {
! /* Look through arrays. */
! while (TYPE_CODE (field_type) == TYPE_CODE_ARRAY)
! {
! field_type = TYPE_TARGET_TYPE (field_type);
! field_type = check_typedef (field_type);
! field_len = TYPE_LENGTH (field_type);
! }
!
! /* If the field's alignment is finer than the structs, we
! won't be in registers. */
! if (field_len < align)
! return 0;
!
! /* If the field itself is a struct or union, then check it
! can be passed in registers. */
! if ((TYPE_CODE (field_type) == TYPE_CODE_STRUCT
! || TYPE_CODE (field_type) == TYPE_CODE_UNION)
! && !m68k_reg_struct_return_p (gdbarch, field_type))
! return 0;
! }
! else
! {
! /* If this field accounts for the whole union, remember it.
! Note that we remember the last such field to match GCC's
! algorithm. */
! if (field_len == len)
! union_field_type = field_type;
! }
! }
!
! if (code == TYPE_CODE_UNION)
! {
! if (!union_field_type)
! return 0;
! /* Look through arrays. */
! while (TYPE_CODE (union_field_type) == TYPE_CODE_ARRAY)
! {
! union_field_type = TYPE_TARGET_TYPE (union_field_type);
! union_field_type = check_typedef (union_field_type);
! }
! /* If this field's alignment is too small, then we won't be in
! registers. */
! if (TYPE_LENGTH (union_field_type) < align)
! return 0;
!
! if (TYPE_CODE (union_field_type) == TYPE_CODE_STRUCT
! || TYPE_CODE (union_field_type) == TYPE_CODE_UNION)
! return m68k_reg_struct_return_p (gdbarch, union_field_type);
! }
!
! /* It will be returned in registers */
! return 1;
}
/* Determine, for architecture GDBARCH, how a return value of TYPE
*************** m68k_svr4_return_value (struct gdbarch *
*** 370,394 ****
if ((code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION)
&& !m68k_reg_struct_return_p (gdbarch, type))
{
! /* The System V ABI says that:
!
! "A function returning a structure or union also sets %a0 to
! the value it finds in %a0. Thus when the caller receives
! control again, the address of the returned object resides in
! register %a0."
!
! So the ABI guarantees that we can always find the return
! value just after the function has returned. */
!
! if (readbuf)
! {
! ULONGEST addr;
!
! regcache_raw_read_unsigned (regcache, M68K_A0_REGNUM, &addr);
! read_memory (addr, readbuf, TYPE_LENGTH (type));
! }
!
! return RETURN_VALUE_ABI_RETURNS_ADDRESS;
}
/* This special case is for structures consisting of a single
--- 457,467 ----
if ((code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION)
&& !m68k_reg_struct_return_p (gdbarch, type))
{
! /* Although they SYSV ABI specifies that a function returning a
! structure this way should preserve %a0, GCC doesn't do that.
! Furthermore there's no point changeing GCC to make it do it,
! as that would just be bloat. */
! return RETURN_VALUE_STRUCT_CONVENTION;
}
/* This special case is for structures consisting of a single
*************** m68k_push_dummy_call (struct gdbarch *gd
*** 423,428 ****
--- 496,504 ----
gdb_byte buf[4];
int i;
+ /* Align the stack down to 4 bytes. Needed for coldfire. */
+ sp &= ~3;
+
/* Push arguments in reverse order. */
for (i = nargs - 1; i >= 0; i--)
{
*************** m68k_svr4_init_abi (struct gdbarch_info
*** 1102,1109 ****
/* SVR4 uses a different calling convention. */
set_gdbarch_return_value (gdbarch, m68k_svr4_return_value);
! /* SVR4 uses %a0 instead of %a1. */
tdep->struct_value_regnum = M68K_A0_REGNUM;
}
\f
--- 1178,1199 ----
/* SVR4 uses a different calling convention. */
set_gdbarch_return_value (gdbarch, m68k_svr4_return_value);
! /* SVR4 uses %a0. */
tdep->struct_value_regnum = M68K_A0_REGNUM;
+ tdep->struct_return = reg_struct_return;
+ }
+
+ /* a.out */
+
+ void
+ m68k_aout_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+ {
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ set_gdbarch_return_value (gdbarch, m68k_return_value);
+
+ tdep->struct_value_regnum = M68K_A1_REGNUM;
+ tdep->struct_return = reg_struct_return;
}
\f
*************** m68k_gdbarch_init (struct gdbarch_info i
*** 1151,1158 ****
set_gdbarch_register_to_value (gdbarch, m68k_register_to_value);
set_gdbarch_value_to_register (gdbarch, m68k_value_to_register);
set_gdbarch_push_dummy_call (gdbarch, m68k_push_dummy_call);
! set_gdbarch_return_value (gdbarch, m68k_return_value);
/* Disassembler. */
set_gdbarch_print_insn (gdbarch, print_insn_m68k);
--- 1241,1253 ----
set_gdbarch_register_to_value (gdbarch, m68k_register_to_value);
set_gdbarch_value_to_register (gdbarch, m68k_value_to_register);
+ /* Function call & return */
set_gdbarch_push_dummy_call (gdbarch, m68k_push_dummy_call);
! /* These values are for bare metal -- os specific ABIs can override
! them */
! set_gdbarch_return_value (gdbarch, m68k_svr4_return_value);
! tdep->struct_value_regnum = M68K_A0_REGNUM;
! tdep->struct_return = reg_struct_return;
/* Disassembler. */
set_gdbarch_print_insn (gdbarch, print_insn_m68k);
*************** m68k_gdbarch_init (struct gdbarch_info i
*** 1163,1170 ****
#else
tdep->jb_pc = -1;
#endif
- tdep->struct_value_regnum = M68K_A1_REGNUM;
- tdep->struct_return = reg_struct_return;
/* Frame unwinder. */
set_gdbarch_unwind_dummy_id (gdbarch, m68k_unwind_dummy_id);
--- 1258,1263 ----
Index: m68k-tdep.h
===================================================================
RCS file: /cvs/src/src/gdb/m68k-tdep.h,v
retrieving revision 1.10
diff -c -3 -p -r1.10 m68k-tdep.h
*** m68k-tdep.h 17 Dec 2005 22:34:01 -0000 1.10
--- m68k-tdep.h 5 Jun 2006 15:16:56 -0000
*************** struct gdbarch_tdep
*** 80,85 ****
--- 80,87 ----
/* Initialize a SVR4 architecture variant. */
extern void m68k_svr4_init_abi (struct gdbarch_info, struct gdbarch *);
+ /* Initialize a aout architecture variant. */
+ extern void m68k_aout_init_abi (struct gdbarch_info, struct gdbarch *);
\f
/* Functions exported from m68kbsd-tdep.c. */
Index: m68kbsd-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/m68kbsd-tdep.c,v
retrieving revision 1.7
diff -c -3 -p -r1.7 m68kbsd-tdep.c
*** m68kbsd-tdep.c 17 Dec 2005 22:34:01 -0000 1.7
--- m68kbsd-tdep.c 5 Jun 2006 15:16:56 -0000
*************** m68kbsd_aout_init_abi (struct gdbarch_in
*** 206,212 ****
m68kbsd_init_abi (info, gdbarch);
! tdep->struct_return = reg_struct_return;
tramp_frame_prepend_unwinder (gdbarch, &m68kobsd_sigtramp);
}
--- 206,212 ----
m68kbsd_init_abi (info, gdbarch);
! m68k_aout_init_abi (info, gdbarch);
tramp_frame_prepend_unwinder (gdbarch, &m68kobsd_sigtramp);
}
*************** m68kbsd_elf_init_abi (struct gdbarch_inf
*** 222,227 ****
--- 222,228 ----
/* NetBSD ELF uses the SVR4 ABI. */
m68k_svr4_init_abi (info, gdbarch);
+ /* But with pcc structure return */
tdep->struct_return = pcc_struct_return;
/* NetBSD ELF uses SVR4-style shared libraries. */
Index: m68klinux-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/m68klinux-tdep.c,v
retrieving revision 1.18
diff -c -3 -p -r1.18 m68klinux-tdep.c
*** m68klinux-tdep.c 20 Apr 2006 17:29:47 -0000 1.18
--- m68klinux-tdep.c 5 Jun 2006 15:16:56 -0000
*************** m68k_linux_init_abi (struct gdbarch_info
*** 291,298 ****
address to store a structure value. It also returns small
structures in registers instead of memory. */
m68k_svr4_init_abi (info, gdbarch);
tdep->struct_value_regnum = M68K_A1_REGNUM;
- tdep->struct_return = reg_struct_return;
frame_unwind_append_sniffer (gdbarch, m68k_linux_sigtramp_frame_sniffer);
--- 291,298 ----
address to store a structure value. It also returns small
structures in registers instead of memory. */
m68k_svr4_init_abi (info, gdbarch);
+ /* But the struct pointer is in %a1 */
tdep->struct_value_regnum = M68K_A1_REGNUM;
frame_unwind_append_sniffer (gdbarch, m68k_linux_sigtramp_frame_sniffer);
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [m68k] fix return value extraction
2006-06-05 15:26 [m68k] fix return value extraction Nathan Sidwell
@ 2006-06-05 16:51 ` Andreas Schwab
2006-06-06 10:18 ` Nathan Sidwell
2006-06-09 10:13 ` Andreas Schwab
1 sibling, 1 reply; 8+ messages in thread
From: Andreas Schwab @ 2006-06-05 16:51 UTC (permalink / raw)
To: Nathan Sidwell; +Cc: gdb-patches
Nathan Sidwell <nathan@codesourcery.com> writes:
> *) GCC never sets %a0 to point to a returned structure. Neither does it
> return pointer values in %a0.
On m68k-linux, which uses the SVR4 ABI (or a close variant thereof) it
does return pointer values in %a0.
Andreas.
--
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux Products GmbH, MaxfeldstraÃe 5, 90409 Nürnberg, Germany
PGP key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5
"And now for something completely different."
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [m68k] fix return value extraction
2006-06-05 16:51 ` Andreas Schwab
@ 2006-06-06 10:18 ` Nathan Sidwell
2006-06-06 10:50 ` Andreas Schwab
2006-06-17 12:54 ` Andreas Schwab
0 siblings, 2 replies; 8+ messages in thread
From: Nathan Sidwell @ 2006-06-06 10:18 UTC (permalink / raw)
To: Andreas Schwab; +Cc: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 596 bytes --]
Andreas Schwab wrote:
> Nathan Sidwell <nathan@codesourcery.com> writes:
>
>
>>*) GCC never sets %a0 to point to a returned structure. Neither does it
>>return pointer values in %a0.
>
>
> On m68k-linux, which uses the SVR4 ABI (or a close variant thereof) it
> does return pointer values in %a0.
ah, yes. this variant of my patch adds a ptr_value_regnum field to the tdep
structure to account for this difference.
ok?
nathan
--
Nathan Sidwell :: http://www.codesourcery.com :: CodeSourcery
nathan@codesourcery.com :: http://www.planetfall.pwp.blueyonder.co.uk
[-- Attachment #2: call-ret.patch --]
[-- Type: text/x-patch, Size: 14096 bytes --]
2006-06-06 Nathan Sidwell <nathan@codesourcery.com>
* gdb/configure.tgt (gdb_osabi): uclinux is like linux.
* gdb/m68k-tdep.c (m68k_svr4_extract_return_value): Use
tdep->ptr_value_regnum for pointer returns.
(m68k_svr4_store_return_value): Likewise.
(m68k_reg_struct_return_p): Duplicate gcc's struct mode algorithm.
(m68k_svr4_return_value) Use VALUE_STRUCT_CONVENTION. do not rely
on %a0.
(m68k_push_dummy_call): Force stack alignment.
(m68k_svr4_init_abi): Set struct_return convention & pointer value
regnum.
(m68k_aout_init_abi): New.
(m68k_gdbarch_init): Default to bare elf ABI that gcc provides.
* gdb/m68k-tdep.h (m68k_aout_init_abi): Declare.
(struct gdbarch_tdep): Add ptr_value_regnum field.
* gdb/m68kbsd-tdep.c (m68kbsd_aout_init_abi): Use m68k_aout_init_abi.
(m68kbsd_elf_init_abi): Add comment.
* gdb/m68klinux-tdep.c (m68k_linux_init_abi): Just set the struct
pointer register here.
Index: configure.tgt
===================================================================
RCS file: /cvs/src/src/gdb/configure.tgt,v
retrieving revision 1.172
diff -c -3 -p -r1.172 configure.tgt
*** configure.tgt 20 Apr 2006 23:18:48 -0000 1.172
--- configure.tgt 6 Jun 2006 10:15:55 -0000
*************** esac
*** 223,228 ****
--- 223,229 ----
case "${target}" in
*-*-freebsd*) gdb_osabi=GDB_OSABI_FREEBSD_ELF ;;
*-*-linux*) gdb_osabi=GDB_OSABI_LINUX ;;
+ *-*-uclinux*) gdb_osabi=GDB_OSABI_LINUX ;;
*-*-nto*) gdb_osabi=GDB_OSABI_QNXNTO ;;
m68*-*-openbsd* | m88*-*-openbsd* | vax-*-openbsd*) ;;
*-*-openbsd*) gdb_osabi=GDB_OSABI_OPENBSD_ELF ;;
Index: m68k-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/m68k-tdep.c,v
retrieving revision 1.105
diff -c -3 -p -r1.105 m68k-tdep.c
*** m68k-tdep.c 17 Dec 2005 22:34:01 -0000 1.105
--- m68k-tdep.c 6 Jun 2006 10:15:56 -0000
*************** m68k_svr4_extract_return_value (struct t
*** 253,259 ****
convert_typed_floating (buf, builtin_type_m68881_ext, valbuf, type);
}
else if (TYPE_CODE (type) == TYPE_CODE_PTR && len == 4)
! regcache_raw_read (regcache, M68K_A0_REGNUM, valbuf);
else
m68k_extract_return_value (type, regcache, valbuf);
}
--- 253,261 ----
convert_typed_floating (buf, builtin_type_m68881_ext, valbuf, type);
}
else if (TYPE_CODE (type) == TYPE_CODE_PTR && len == 4)
! regcache_raw_read (regcache,
! gdbarch_tdep (current_gdbarch)->ptr_value_regnum,
! valbuf);
else
m68k_extract_return_value (type, regcache, valbuf);
}
*************** m68k_svr4_store_return_value (struct typ
*** 292,301 ****
regcache_raw_write (regcache, M68K_FP0_REGNUM, buf);
}
else if (TYPE_CODE (type) == TYPE_CODE_PTR && len == 4)
! {
! regcache_raw_write (regcache, M68K_A0_REGNUM, valbuf);
! regcache_raw_write (regcache, M68K_D0_REGNUM, valbuf);
! }
else
m68k_store_return_value (type, regcache, valbuf);
}
--- 294,302 ----
regcache_raw_write (regcache, M68K_FP0_REGNUM, buf);
}
else if (TYPE_CODE (type) == TYPE_CODE_PTR && len == 4)
! regcache_raw_write (regcache,
! gdbarch_tdep (current_gdbarch)->ptr_value_regnum,
! valbuf);
else
m68k_store_return_value (type, regcache, valbuf);
}
*************** m68k_reg_struct_return_p (struct gdbarch
*** 310,322 ****
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
enum type_code code = TYPE_CODE (type);
int len = TYPE_LENGTH (type);
gdb_assert (code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION);
if (tdep->struct_return == pcc_struct_return)
return 0;
! return (len == 1 || len == 2 || len == 4 || len == 8);
}
/* Determine, for architecture GDBARCH, how a return value of TYPE
--- 311,407 ----
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
enum type_code code = TYPE_CODE (type);
int len = TYPE_LENGTH (type);
+ int align;
+ int ix;
+ struct type *union_field_type = NULL;
gdb_assert (code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION);
if (tdep->struct_return == pcc_struct_return)
return 0;
! /* Unfortunately GCC incorrectly implements this optimization.
! Rather than simply return all small structs, or even just those
! of size 2^N, it uses the mode of the structure to determine this.
! BLKmode structs will be returned by memory and QI,HI,SI,DI,SF&DF
! mode structs will be returned by register. For m68k a struct is
! BLKmode unless it's size is 2^N and the mode for that size does
! not need a greater alignment than the structure itself. Unions
! will get the mode of last member whose size matches that of the
! union itself. This is horrible. */
!
! if (len > 8 || (len & -len) != len)
! /* Length is not 2^n or is too big. */
! return 0;
!
! align = len > 4 ? 4 : len;
! for (ix = 0; ix != TYPE_NFIELDS (type); ix++)
! {
! struct type *field_type;
! int field_len;
!
! if (TYPE_FIELD_STATIC (type, ix))
! /* Skip static fields. */
! continue;
!
! field_type = TYPE_FIELD_TYPE (type, ix);
! field_type = check_typedef (field_type);
! field_len = TYPE_LENGTH (field_type);
!
! if (code == TYPE_CODE_STRUCT)
! {
! /* Look through arrays. */
! while (TYPE_CODE (field_type) == TYPE_CODE_ARRAY)
! {
! field_type = TYPE_TARGET_TYPE (field_type);
! field_type = check_typedef (field_type);
! field_len = TYPE_LENGTH (field_type);
! }
!
! /* If the field's alignment is finer than the structs, we
! won't be in registers. */
! if (field_len < align)
! return 0;
!
! /* If the field itself is a struct or union, then check it
! can be passed in registers. */
! if ((TYPE_CODE (field_type) == TYPE_CODE_STRUCT
! || TYPE_CODE (field_type) == TYPE_CODE_UNION)
! && !m68k_reg_struct_return_p (gdbarch, field_type))
! return 0;
! }
! else
! {
! /* If this field accounts for the whole union, remember it.
! Note that we remember the last such field to match GCC's
! algorithm. */
! if (field_len == len)
! union_field_type = field_type;
! }
! }
!
! if (code == TYPE_CODE_UNION)
! {
! if (!union_field_type)
! return 0;
! /* Look through arrays. */
! while (TYPE_CODE (union_field_type) == TYPE_CODE_ARRAY)
! {
! union_field_type = TYPE_TARGET_TYPE (union_field_type);
! union_field_type = check_typedef (union_field_type);
! }
! /* If this field's alignment is too small, then we won't be in
! registers. */
! if (TYPE_LENGTH (union_field_type) < align)
! return 0;
!
! if (TYPE_CODE (union_field_type) == TYPE_CODE_STRUCT
! || TYPE_CODE (union_field_type) == TYPE_CODE_UNION)
! return m68k_reg_struct_return_p (gdbarch, union_field_type);
! }
!
! /* It will be returned in registers */
! return 1;
}
/* Determine, for architecture GDBARCH, how a return value of TYPE
*************** m68k_svr4_return_value (struct gdbarch *
*** 370,394 ****
if ((code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION)
&& !m68k_reg_struct_return_p (gdbarch, type))
{
! /* The System V ABI says that:
!
! "A function returning a structure or union also sets %a0 to
! the value it finds in %a0. Thus when the caller receives
! control again, the address of the returned object resides in
! register %a0."
!
! So the ABI guarantees that we can always find the return
! value just after the function has returned. */
!
! if (readbuf)
! {
! ULONGEST addr;
!
! regcache_raw_read_unsigned (regcache, M68K_A0_REGNUM, &addr);
! read_memory (addr, readbuf, TYPE_LENGTH (type));
! }
!
! return RETURN_VALUE_ABI_RETURNS_ADDRESS;
}
/* This special case is for structures consisting of a single
--- 455,465 ----
if ((code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION)
&& !m68k_reg_struct_return_p (gdbarch, type))
{
! /* Although they SYSV ABI specifies that a function returning a
! structure this way should preserve %a0, GCC doesn't do that.
! Furthermore there's no point changeing GCC to make it do it,
! as that would just be bloat. */
! return RETURN_VALUE_STRUCT_CONVENTION;
}
/* This special case is for structures consisting of a single
*************** m68k_push_dummy_call (struct gdbarch *gd
*** 423,428 ****
--- 494,502 ----
gdb_byte buf[4];
int i;
+ /* Align the stack down to 4 bytes. Needed for coldfire. */
+ sp &= ~3;
+
/* Push arguments in reverse order. */
for (i = nargs - 1; i >= 0; i--)
{
*************** m68k_svr4_init_abi (struct gdbarch_info
*** 1102,1109 ****
/* SVR4 uses a different calling convention. */
set_gdbarch_return_value (gdbarch, m68k_svr4_return_value);
! /* SVR4 uses %a0 instead of %a1. */
tdep->struct_value_regnum = M68K_A0_REGNUM;
}
\f
--- 1176,1202 ----
/* SVR4 uses a different calling convention. */
set_gdbarch_return_value (gdbarch, m68k_svr4_return_value);
! /* SVR4 uses %a0. */
tdep->struct_value_regnum = M68K_A0_REGNUM;
+ tdep->struct_return = reg_struct_return;
+ /* Pointers are returned in %a0 */
+ tdep->ptr_value_regnum = M68K_A0_REGNUM;
+ }
+
+ /* a.out */
+
+ void
+ m68k_aout_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+ {
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ set_gdbarch_return_value (gdbarch, m68k_return_value);
+
+ /* aout uses %a1 */
+ tdep->struct_value_regnum = M68K_A1_REGNUM;
+ tdep->struct_return = reg_struct_return;
+ /* Pointers are returned in %a0 */
+ tdep->ptr_value_regnum = M68K_A0_REGNUM;
}
\f
*************** m68k_gdbarch_init (struct gdbarch_info i
*** 1151,1158 ****
set_gdbarch_register_to_value (gdbarch, m68k_register_to_value);
set_gdbarch_value_to_register (gdbarch, m68k_value_to_register);
set_gdbarch_push_dummy_call (gdbarch, m68k_push_dummy_call);
! set_gdbarch_return_value (gdbarch, m68k_return_value);
/* Disassembler. */
set_gdbarch_print_insn (gdbarch, print_insn_m68k);
--- 1244,1257 ----
set_gdbarch_register_to_value (gdbarch, m68k_register_to_value);
set_gdbarch_value_to_register (gdbarch, m68k_value_to_register);
+ /* Function call & return */
set_gdbarch_push_dummy_call (gdbarch, m68k_push_dummy_call);
! /* These values are for bare metal -- os specific ABIs can override
! them */
! set_gdbarch_return_value (gdbarch, m68k_svr4_return_value);
! tdep->struct_value_regnum = M68K_A0_REGNUM;
! tdep->struct_return = reg_struct_return;
! tdep->ptr_value_regnum = M68K_D0_REGNUM;
/* Disassembler. */
set_gdbarch_print_insn (gdbarch, print_insn_m68k);
*************** m68k_gdbarch_init (struct gdbarch_info i
*** 1163,1170 ****
#else
tdep->jb_pc = -1;
#endif
- tdep->struct_value_regnum = M68K_A1_REGNUM;
- tdep->struct_return = reg_struct_return;
/* Frame unwinder. */
set_gdbarch_unwind_dummy_id (gdbarch, m68k_unwind_dummy_id);
--- 1262,1267 ----
Index: m68k-tdep.h
===================================================================
RCS file: /cvs/src/src/gdb/m68k-tdep.h,v
retrieving revision 1.10
diff -c -3 -p -r1.10 m68k-tdep.h
*** m68k-tdep.h 17 Dec 2005 22:34:01 -0000 1.10
--- m68k-tdep.h 6 Jun 2006 10:15:56 -0000
*************** struct gdbarch_tdep
*** 76,85 ****
--- 76,90 ----
/* Convention for returning structures. */
enum struct_return struct_return;
+
+ /* Register in which pointers are returned. */
+ int ptr_value_regnum;
};
/* Initialize a SVR4 architecture variant. */
extern void m68k_svr4_init_abi (struct gdbarch_info, struct gdbarch *);
+ /* Initialize a aout architecture variant. */
+ extern void m68k_aout_init_abi (struct gdbarch_info, struct gdbarch *);
\f
/* Functions exported from m68kbsd-tdep.c. */
Index: m68kbsd-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/m68kbsd-tdep.c,v
retrieving revision 1.7
diff -c -3 -p -r1.7 m68kbsd-tdep.c
*** m68kbsd-tdep.c 17 Dec 2005 22:34:01 -0000 1.7
--- m68kbsd-tdep.c 6 Jun 2006 10:15:56 -0000
*************** m68kbsd_aout_init_abi (struct gdbarch_in
*** 206,212 ****
m68kbsd_init_abi (info, gdbarch);
! tdep->struct_return = reg_struct_return;
tramp_frame_prepend_unwinder (gdbarch, &m68kobsd_sigtramp);
}
--- 206,212 ----
m68kbsd_init_abi (info, gdbarch);
! m68k_aout_init_abi (info, gdbarch);
tramp_frame_prepend_unwinder (gdbarch, &m68kobsd_sigtramp);
}
*************** m68kbsd_elf_init_abi (struct gdbarch_inf
*** 222,227 ****
--- 222,228 ----
/* NetBSD ELF uses the SVR4 ABI. */
m68k_svr4_init_abi (info, gdbarch);
+ /* But with pcc structure return */
tdep->struct_return = pcc_struct_return;
/* NetBSD ELF uses SVR4-style shared libraries. */
Index: m68klinux-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/m68klinux-tdep.c,v
retrieving revision 1.18
diff -c -3 -p -r1.18 m68klinux-tdep.c
*** m68klinux-tdep.c 20 Apr 2006 17:29:47 -0000 1.18
--- m68klinux-tdep.c 6 Jun 2006 10:15:56 -0000
*************** m68k_linux_init_abi (struct gdbarch_info
*** 291,298 ****
address to store a structure value. It also returns small
structures in registers instead of memory. */
m68k_svr4_init_abi (info, gdbarch);
tdep->struct_value_regnum = M68K_A1_REGNUM;
- tdep->struct_return = reg_struct_return;
frame_unwind_append_sniffer (gdbarch, m68k_linux_sigtramp_frame_sniffer);
--- 291,298 ----
address to store a structure value. It also returns small
structures in registers instead of memory. */
m68k_svr4_init_abi (info, gdbarch);
+ /* But the struct pointer is in %a1 */
tdep->struct_value_regnum = M68K_A1_REGNUM;
frame_unwind_append_sniffer (gdbarch, m68k_linux_sigtramp_frame_sniffer);
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [m68k] fix return value extraction
2006-06-06 10:18 ` Nathan Sidwell
@ 2006-06-06 10:50 ` Andreas Schwab
2006-06-06 12:31 ` Daniel Jacobowitz
2006-06-17 12:54 ` Andreas Schwab
1 sibling, 1 reply; 8+ messages in thread
From: Andreas Schwab @ 2006-06-06 10:50 UTC (permalink / raw)
To: Nathan Sidwell; +Cc: gdb-patches
Nathan Sidwell <nathan@codesourcery.com> writes:
> + /* a.out */
> +
> + void
> + m68k_aout_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
> + {
> + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
> +
> + set_gdbarch_return_value (gdbarch, m68k_return_value);
> +
> + /* aout uses %a1 */
> + tdep->struct_value_regnum = M68K_A1_REGNUM;
> + tdep->struct_return = reg_struct_return;
> + /* Pointers are returned in %a0 */
> + tdep->ptr_value_regnum = M68K_A0_REGNUM;
I don't think this is correct. The GCC default for m68k is the old Sun3
ABI, which returns everything in %d0 and uses pcc structure return.
Andreas.
--
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux Products GmbH, MaxfeldstraÃe 5, 90409 Nürnberg, Germany
PGP key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5
"And now for something completely different."
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [m68k] fix return value extraction
2006-06-06 10:50 ` Andreas Schwab
@ 2006-06-06 12:31 ` Daniel Jacobowitz
0 siblings, 0 replies; 8+ messages in thread
From: Daniel Jacobowitz @ 2006-06-06 12:31 UTC (permalink / raw)
To: Andreas Schwab; +Cc: Nathan Sidwell, gdb-patches
On Tue, Jun 06, 2006 at 12:50:41PM +0200, Andreas Schwab wrote:
> Nathan Sidwell <nathan@codesourcery.com> writes:
>
> > + /* a.out */
> > +
> > + void
> > + m68k_aout_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
> > + {
> > + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
> > +
> > + set_gdbarch_return_value (gdbarch, m68k_return_value);
> > +
> > + /* aout uses %a1 */
> > + tdep->struct_value_regnum = M68K_A1_REGNUM;
> > + tdep->struct_return = reg_struct_return;
> > + /* Pointers are returned in %a0 */
> > + tdep->ptr_value_regnum = M68K_A0_REGNUM;
>
> I don't think this is correct. The GCC default for m68k is the old Sun3
> ABI, which returns everything in %d0 and uses pcc structure return.
Ah - sort of, but not. I spent a while last week disecting the
configuration defaults when Nathan asked me about this. In fact, while
m68k.h defaults to pcc structure return, the "embedded" configurations
all turn it right back off again - including m68k-aout, m68k-coff,
m68k-elf, and m68k-rtems. The only thing I saw which definitively used
it was NetBSD ELF.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [m68k] fix return value extraction
2006-06-05 15:26 [m68k] fix return value extraction Nathan Sidwell
2006-06-05 16:51 ` Andreas Schwab
@ 2006-06-09 10:13 ` Andreas Schwab
2006-06-09 10:15 ` Nathan Sidwell
1 sibling, 1 reply; 8+ messages in thread
From: Andreas Schwab @ 2006-06-09 10:13 UTC (permalink / raw)
To: Nathan Sidwell; +Cc: gdb-patches
Nathan Sidwell <nathan@codesourcery.com> writes:
> *************** m68k_push_dummy_call (struct gdbarch *gd
> *** 423,428 ****
> --- 496,504 ----
> gdb_byte buf[4];
> int i;
>
> + /* Align the stack down to 4 bytes. Needed for coldfire. */
> + sp &= ~3;
> +
> /* Push arguments in reverse order. */
> for (i = nargs - 1; i >= 0; i--)
> {
I think this should be done through gdbarch_frame_align.
Andreas.
--
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux Products GmbH, MaxfeldstraÃe 5, 90409 Nürnberg, Germany
PGP key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5
"And now for something completely different."
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [m68k] fix return value extraction
2006-06-09 10:13 ` Andreas Schwab
@ 2006-06-09 10:15 ` Nathan Sidwell
0 siblings, 0 replies; 8+ messages in thread
From: Nathan Sidwell @ 2006-06-09 10:15 UTC (permalink / raw)
To: Andreas Schwab; +Cc: gdb-patches
Andreas Schwab wrote:
>
> I think this should be done through gdbarch_frame_align.
ok. I was unaware of such a callback. thanks for pointing me at it.
nathan
--
Nathan Sidwell :: http://www.codesourcery.com :: CodeSourcery
nathan@codesourcery.com :: http://www.planetfall.pwp.blueyonder.co.uk
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [m68k] fix return value extraction
2006-06-06 10:18 ` Nathan Sidwell
2006-06-06 10:50 ` Andreas Schwab
@ 2006-06-17 12:54 ` Andreas Schwab
1 sibling, 0 replies; 8+ messages in thread
From: Andreas Schwab @ 2006-06-17 12:54 UTC (permalink / raw)
To: Nathan Sidwell; +Cc: gdb-patches
Nathan Sidwell <nathan@codesourcery.com> writes:
> --- 455,465 ----
> if ((code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION)
> && !m68k_reg_struct_return_p (gdbarch, type))
> {
> ! /* Although they SYSV ABI specifies that a function returning a
> ! structure this way should preserve %a0, GCC doesn't do that.
At least on m68k-linux it does, and probably all targets using
m68k_function_value (ie. following the SVR4 ABI) do the same.
Andreas.
--
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux Products GmbH, MaxfeldstraÃe 5, 90409 Nürnberg, Germany
PGP key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5
"And now for something completely different."
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2006-06-17 12:54 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-06-05 15:26 [m68k] fix return value extraction Nathan Sidwell
2006-06-05 16:51 ` Andreas Schwab
2006-06-06 10:18 ` Nathan Sidwell
2006-06-06 10:50 ` Andreas Schwab
2006-06-06 12:31 ` Daniel Jacobowitz
2006-06-17 12:54 ` Andreas Schwab
2006-06-09 10:13 ` Andreas Schwab
2006-06-09 10:15 ` Nathan Sidwell
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox