2006-06-06 Nathan Sidwell * 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; } --- 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; } *************** 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 *); /* 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);