diff options
author | Jason Thorpe <thorpej@netbsd.org> | 2002-05-30 01:21:53 +0000 |
---|---|---|
committer | Jason Thorpe <thorpej@netbsd.org> | 2002-05-30 01:21:53 +0000 |
commit | 7b112f9c0c091098e7b67fbd4b15c445effebfb4 (patch) | |
tree | 8b702b82bd291ba757afd3d17d5a7da2781ed4e9 /gdb/ppc-linux-tdep.c | |
parent | d79e4ea30edea4b1b24d8e03c7d117ce8084811e (diff) | |
download | gdb-7b112f9c0c091098e7b67fbd4b15c445effebfb4.zip gdb-7b112f9c0c091098e7b67fbd4b15c445effebfb4.tar.gz gdb-7b112f9c0c091098e7b67fbd4b15c445effebfb4.tar.bz2 |
* Makefile.in (ppc_tdep_h): Define.
(ppc-linux-nat.o)
(ppc-linux-tdep.o)
(rs6000-tdep.o): Use $(ppc_tdep_h).
(ppc-sysv-tdep.o)
(ppcnbsd-nat.o)
(ppcnbsd-tdep.o): New dependency lists.
* ppc-tdep.h: Use generic OS ABI framework.
* ppc-linux-tdep.c (_initialize_ppc_linux_tdep,
ppc_linux_init_abi): New functions.
(ppc_sysv_abi_broken_use_struct_convention)
(ppc_sysv_abi_use_struct_convention)
(ppc_sysv_abi_push_arguments): Move to...
* ppc-sysv-tdep.c: ...here.
* ppcnbsd-nat.c: Don't include gdbcore.h and regcache.h.
* rs6000-tdep.c (process_note_abi_tag_sections)
(get_elfosabi): Remove.
(rs6000_gdbarch_init): Use generic OS ABI framework.
(rs6000_dump_tdep): New function.
(_initialize_rs6000_tdep): Use gdbarch_register.
* config/powerpc/linux.mt (TDEPFILES): Add ppc-sysv-tdep.o.
* config/powerpc/nbsd.mh (NATDEPFILES): Remove solib-legacy.o.
* config/powerpc/aix.mt (TDEPFILES): Use ppc-sysv-tdep.o instead
of ppc-linux-tdep.o.
* config/powerpc/nbsd.mt (TDEPFILES): Likewise.
* config/powerpc/ppc-eabi.mt (TDEPFILES): Likewise.
* config/powerpc/ppc-sim.mt (TDEPFILES): Likewise.
* config/powerpc/ppcle-eabi.mt (TDEPFILES): Likewise.
* config/powerpc/ppcle-sim.mt (TDEPFILES): Likewise.
* config/powerpc/vxworks.mt (TDEPFILES): Likewise.
Diffstat (limited to 'gdb/ppc-linux-tdep.c')
-rw-r--r-- | gdb/ppc-linux-tdep.c | 328 |
1 files changed, 41 insertions, 287 deletions
diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c index f358274..1a88d40 100644 --- a/gdb/ppc-linux-tdep.c +++ b/gdb/ppc-linux-tdep.c @@ -411,293 +411,6 @@ ppc_linux_frame_chain (struct frame_info *thisframe) return rs6000_frame_chain (thisframe); } -/* FIXME: Move the following to rs6000-tdep.c (or some other file where - it may be used generically by ports which use either the SysV ABI or - the EABI */ - -/* Until November 2001, gcc was not complying to the SYSV ABI for - returning structures less than or equal to 8 bytes in size. It was - returning everything in memory. When this was corrected, it wasn't - fixed for native platforms. */ -int -ppc_sysv_abi_broken_use_struct_convention (int gcc_p, struct type *value_type) -{ - if (TYPE_LENGTH (value_type) == 16 - && TYPE_VECTOR (value_type)) - return 0; - - return generic_use_struct_convention (gcc_p, value_type); -} - -/* Structures 8 bytes or less long are returned in the r3 & r4 - registers, according to the SYSV ABI. */ -int -ppc_sysv_abi_use_struct_convention (int gcc_p, struct type *value_type) -{ - if (TYPE_LENGTH (value_type) == 16 - && TYPE_VECTOR (value_type)) - return 0; - - return (TYPE_LENGTH (value_type) > 8); -} - -/* round2 rounds x up to the nearest multiple of s assuming that s is a - power of 2 */ - -#undef round2 -#define round2(x,s) ((((long) (x) - 1) & ~(long)((s)-1)) + (s)) - -/* Pass the arguments in either registers, or in the stack. Using the - ppc sysv ABI, the first eight words of the argument list (that might - be less than eight parameters if some parameters occupy more than one - word) are passed in r3..r10 registers. float and double parameters are - passed in fpr's, in addition to that. Rest of the parameters if any - are passed in user stack. - - If the function is returning a structure, then the return address is passed - in r3, then the first 7 words of the parametes can be passed in registers, - starting from r4. */ - -CORE_ADDR -ppc_sysv_abi_push_arguments (int nargs, struct value **args, CORE_ADDR sp, - int struct_return, CORE_ADDR struct_addr) -{ - int argno; - /* Next available general register for non-float, non-vector arguments. */ - int greg; - /* Next available floating point register for float arguments. */ - int freg; - /* Next available vector register for vector arguments. */ - int vreg; - int argstkspace; - int structstkspace; - int argoffset; - int structoffset; - struct value *arg; - struct type *type; - int len; - char old_sp_buf[4]; - CORE_ADDR saved_sp; - - greg = struct_return ? 4 : 3; - freg = 1; - vreg = 2; - argstkspace = 0; - structstkspace = 0; - - /* Figure out how much new stack space is required for arguments - which don't fit in registers. Unlike the PowerOpen ABI, the - SysV ABI doesn't reserve any extra space for parameters which - are put in registers. */ - for (argno = 0; argno < nargs; argno++) - { - arg = args[argno]; - type = check_typedef (VALUE_TYPE (arg)); - len = TYPE_LENGTH (type); - - if (TYPE_CODE (type) == TYPE_CODE_FLT) - { - if (freg <= 8) - freg++; - else - { - /* SysV ABI converts floats to doubles when placed in - memory and requires 8 byte alignment */ - if (argstkspace & 0x4) - argstkspace += 4; - argstkspace += 8; - } - } - else if (TYPE_CODE (type) == TYPE_CODE_INT && len == 8) /* long long */ - { - if (greg > 9) - { - greg = 11; - if (argstkspace & 0x4) - argstkspace += 4; - argstkspace += 8; - } - else - { - if ((greg & 1) == 0) - greg++; - greg += 2; - } - } - else if (!TYPE_VECTOR (type)) - { - if (len > 4 - || TYPE_CODE (type) == TYPE_CODE_STRUCT - || TYPE_CODE (type) == TYPE_CODE_UNION) - { - /* Rounding to the nearest multiple of 8 may not be necessary, - but it is safe. Particularly since we don't know the - field types of the structure */ - structstkspace += round2 (len, 8); - } - if (greg <= 10) - greg++; - else - argstkspace += 4; - } - else - { - if (len == 16 - && TYPE_CODE (type) == TYPE_CODE_ARRAY - && TYPE_VECTOR (type)) - { - if (vreg <= 13) - vreg++; - else - { - /* Vector arguments must be aligned to 16 bytes on - the stack. */ - argstkspace += round2 (argstkspace, 16); - argstkspace += 16; - } - } - } - } - - /* Get current SP location */ - saved_sp = read_sp (); - - sp -= argstkspace + structstkspace; - - /* Allocate space for backchain and callee's saved lr */ - sp -= 8; - - /* Make sure that we maintain 16 byte alignment */ - sp &= ~0x0f; - - /* Update %sp before proceeding any further */ - write_register (SP_REGNUM, sp); - - /* write the backchain */ - store_address (old_sp_buf, 4, saved_sp); - write_memory (sp, old_sp_buf, 4); - - argoffset = 8; - structoffset = argoffset + argstkspace; - freg = 1; - greg = 3; - vreg = 2; - /* Fill in r3 with the return structure, if any */ - if (struct_return) - { - char val_buf[4]; - store_address (val_buf, 4, struct_addr); - memcpy (®isters[REGISTER_BYTE (greg)], val_buf, 4); - greg++; - } - /* Now fill in the registers and stack... */ - for (argno = 0; argno < nargs; argno++) - { - arg = args[argno]; - type = check_typedef (VALUE_TYPE (arg)); - len = TYPE_LENGTH (type); - - if (TYPE_CODE (type) == TYPE_CODE_FLT) - { - if (freg <= 8) - { - if (len > 8) - printf_unfiltered ( - "Fatal Error: a floating point parameter #%d with a size > 8 is found!\n", argno); - memcpy (®isters[REGISTER_BYTE (FP0_REGNUM + freg)], - VALUE_CONTENTS (arg), len); - freg++; - } - else - { - /* SysV ABI converts floats to doubles when placed in - memory and requires 8 byte alignment */ - /* FIXME: Convert floats to doubles */ - if (argoffset & 0x4) - argoffset += 4; - write_memory (sp + argoffset, (char *) VALUE_CONTENTS (arg), len); - argoffset += 8; - } - } - else if (TYPE_CODE (type) == TYPE_CODE_INT && len == 8) /* long long */ - { - if (greg > 9) - { - greg = 11; - if (argoffset & 0x4) - argoffset += 4; - write_memory (sp + argoffset, (char *) VALUE_CONTENTS (arg), len); - argoffset += 8; - } - else - { - if ((greg & 1) == 0) - greg++; - - memcpy (®isters[REGISTER_BYTE (greg)], - VALUE_CONTENTS (arg), 4); - memcpy (®isters[REGISTER_BYTE (greg + 1)], - VALUE_CONTENTS (arg) + 4, 4); - greg += 2; - } - } - else if (!TYPE_VECTOR (type)) - { - char val_buf[4]; - if (len > 4 - || TYPE_CODE (type) == TYPE_CODE_STRUCT - || TYPE_CODE (type) == TYPE_CODE_UNION) - { - write_memory (sp + structoffset, VALUE_CONTENTS (arg), len); - store_address (val_buf, 4, sp + structoffset); - structoffset += round2 (len, 8); - } - else - { - memset (val_buf, 0, 4); - memcpy (val_buf, VALUE_CONTENTS (arg), len); - } - if (greg <= 10) - { - memcpy (®isters[REGISTER_BYTE (greg)], val_buf, 4); - greg++; - } - else - { - write_memory (sp + argoffset, val_buf, 4); - argoffset += 4; - } - } - else - { - if (len == 16 - && TYPE_CODE (type) == TYPE_CODE_ARRAY - && TYPE_VECTOR (type)) - { - struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); - char *v_val_buf = alloca (16); - memset (v_val_buf, 0, 16); - memcpy (v_val_buf, VALUE_CONTENTS (arg), len); - if (vreg <= 13) - { - memcpy (®isters[REGISTER_BYTE (tdep->ppc_vr0_regnum - + vreg)], - v_val_buf, 16); - vreg++; - } - else - { - write_memory (sp + argoffset, v_val_buf, 16); - argoffset += 16; - } - } - } - } - - target_store_registers (-1); - return sp; -} - /* ppc_linux_memory_remove_breakpoints attempts to remove a breakpoint in much the same fashion as memory_remove_breakpoint in mem-break.c, but is careful not to write back the previous contents if the code @@ -886,3 +599,44 @@ ppc_linux_svr4_fetch_link_map_offsets (void) return lmp; } + +static void +ppc_linux_init_abi (struct gdbarch_info info, + struct gdbarch *gdbarch) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + /* Until November 2001, gcc was not complying to the SYSV ABI for + returning structures less than or equal to 8 bytes in size. It was + returning everything in memory. When this was corrected, it wasn't + fixed for native platforms. */ + set_gdbarch_use_struct_convention (gdbarch, + ppc_sysv_abi_broken_use_struct_convention); + + if (tdep->wordsize == 4) + { + /* Note: kevinb/2002-04-12: See note in rs6000_gdbarch_init regarding + *_push_arguments(). The same remarks hold for the methods below. */ + set_gdbarch_frameless_function_invocation (gdbarch, + ppc_linux_frameless_function_invocation); + set_gdbarch_frame_chain (gdbarch, ppc_linux_frame_chain); + set_gdbarch_frame_saved_pc (gdbarch, ppc_linux_frame_saved_pc); + + set_gdbarch_frame_init_saved_regs (gdbarch, + ppc_linux_frame_init_saved_regs); + set_gdbarch_init_extra_frame_info (gdbarch, + ppc_linux_init_extra_frame_info); + + set_gdbarch_memory_remove_breakpoint (gdbarch, + ppc_linux_memory_remove_breakpoint); + set_solib_svr4_fetch_link_map_offsets + (gdbarch, ppc_linux_svr4_fetch_link_map_offsets); + } +} + +void +_initialize_ppc_linux_tdep (void) +{ + gdbarch_register_osabi (bfd_arch_powerpc, GDB_OSABI_LINUX, + ppc_linux_init_abi); +} |