+2002-05-20 Jason Thorpe <thorpej@wasabisystems.com>
+
+ * 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.
+
2002-05-29 Jim Blandy <jimb@redhat.com>
* macroscope.c (default_macro_scope): Put `void' in empty argument
monitor_h = monitor.h
objfiles_h = objfiles.h
parser_defs_h = parser-defs.h $(doublest_h)
+ppc_tdep_h = ppc-tdep.h osabi.h
regcache_h = regcache.h
remote_h = remote.h
remote_utils_h = remote-utils.h $(target_h)
nindy-share/ttyflush.c nindy-tdep.c \
ns32k-tdep.c solib-osf.c \
somread.c somsolib.c $(HPREAD_SOURCE) \
- ppc-linux-nat.c ppc-linux-tdep.c \
+ ppc-sysv-tdep.o ppc-linux-nat.c ppc-linux-tdep.c \
+ ppcnbsd-nat.o ppcnbsd-tdep.o \
procfs.c \
remote-adapt.c remote-array.c remote-bug.c remote-e7000.c remote-eb.c \
remote-es.c remote-hms.c remote-mips.c \
$(objfiles_h) $(gdb_stabs_h) $(serial_h) ocd.h $(regcache_h)
ppc-linux-nat.o: ppc-linux-nat.c $(defs_h) $(gdbcore_h) $(frame_h) \
- $(inferior_h) $(target_h) $(regcache_h) ppc-tdep.h
+ $(inferior_h) $(target_h) $(regcache_h) $(ppc_tdep_h)
ppc-linux-tdep.o: ppc-linux-tdep.c $(defs_h) $(gdbcore_h) $(inferior_h) \
- $(target_h) ppc-tdep.h $(regcache_h) $(value_h)
+ $(target_h) $(ppc_tdep_h) $(regcache_h) $(value_h)
+
+ppc-sysv-tdep.o: ppc-sysv-tdep.c $(defs_h) $(gdbcore_h) $(inferior_h) \
+ $(value_h) $(regcache_h) $(ppc_tdep_h)
+
+ppcnbsd-nat.o: ppcnbsd-nat.c $(defs_h) $(inferior_h) $(ppc_tdep_h) \
+ ppcnbsd-tdep.h
+
+ppcnbsd-tdep.o: ppcnbsd-tdep.c $(defs_h) $(gdbcore_h) $(regcache_h) \
+ $(target_h) $(breakpoint_h) $(value_h) $(ppc_tdep_t) ppcnbsd-tdep.h \
+ nbsd-tdep.h
ppcbug-rom.o: ppcbug-rom.c $(monitor_h) $(bfd_h) $(gdb_wait_h) $(defs_h) \
$(gdbcmd_h) $(inferior_h) $(target_h) $(serial_h) $(terminal_h) \
$(gdb_stabs_h) $(regcache_h) $(arch_utils_h)
rs6000-tdep.o: rs6000-tdep.c $(defs_h) $(gdbcore_h) $(inferior_h) \
- $(target_h) ppc-tdep.h $(regcache_h) $(value_h) $(parser_defs_h)
+ $(target_h) $(ppc_tdep_h) $(regcache_h) $(value_h) $(parser_defs_h)
s390-tdep.o: s390-tdep.c $(defs_h) $(arch_utils_h) $(frame_h) $(inferior_h) \
$(symtab_h) $(target_h) $(gdbcore_h) $(gdbcmd_h) $(symfile_h) \
# Target: PowerPC running AIX
-TDEPFILES= rs6000-tdep.o xcoffread.o ppc-linux-tdep.o solib.o solib-svr4.o
+TDEPFILES= rs6000-tdep.o xcoffread.o ppc-sysv-tdep.o solib.o solib-svr4.o
TM_FILE= tm-ppc-aix.h
# Target: Motorola PPC on Linux
-TDEPFILES= rs6000-tdep.o ppc-linux-tdep.o solib.o solib-svr4.o solib-legacy.o
+TDEPFILES= rs6000-tdep.o ppc-linux-tdep.o ppc-sysv-tdep.o solib.o \
+ solib-svr4.o solib-legacy.o
TM_FILE= tm-linux.h
SIM_OBS = remote-sim.o
# Host: PowerPC, running NetBSD
-NATDEPFILES= fork-child.o infptrace.o inftarg.o ppcnbsd-nat.o solib-legacy.o
+NATDEPFILES= fork-child.o infptrace.o inftarg.o ppcnbsd-nat.o
NAT_FILE= nm-nbsd.h
# Target: PowerPC, running NetBSD
-TDEPFILES= rs6000-tdep.o ppcnbsd-tdep.o nbsd-tdep.o ppc-linux-tdep.o corelow.o \
+TDEPFILES= rs6000-tdep.o ppc-sysv-tdep.o ppcnbsd-tdep.o nbsd-tdep.o corelow.o \
solib.o solib-svr4.o
TM_FILE= tm-nbsd.h
# Target: PowerPC running eabi
-TDEPFILES= rs6000-tdep.o monitor.o dsrec.o ppcbug-rom.o dink32-rom.o ppc-bdm.o ocd.o remote-sds.o ppc-linux-tdep.o solib.o solib-svr4.o
+TDEPFILES= rs6000-tdep.o monitor.o dsrec.o ppcbug-rom.o dink32-rom.o ppc-bdm.o ocd.o remote-sds.o ppc-sysv-tdep.o solib.o solib-svr4.o
TM_FILE= tm-ppc-eabi.h
# Target: PowerPC running eabi and including the simulator
-TDEPFILES= rs6000-tdep.o monitor.o dsrec.o ppcbug-rom.o dink32-rom.o ppc-bdm.o ocd.o remote-sds.o ppc-linux-tdep.o solib.o solib-svr4.o
+TDEPFILES= rs6000-tdep.o monitor.o dsrec.o ppcbug-rom.o dink32-rom.o ppc-bdm.o ocd.o remote-sds.o ppc-sysv-tdep.o solib.o solib-svr4.o
TM_FILE= tm-ppc-eabi.h
SIM_OBS = remote-sim.o
# Target: PowerPC running eabi in little endian mode
-TDEPFILES= rs6000-tdep.o monitor.o dsrec.o ppcbug-rom.o ppc-bdm.o ocd.o ppc-linux-tdep.o solib.o solib-svr4.o
+TDEPFILES= rs6000-tdep.o monitor.o dsrec.o ppcbug-rom.o ppc-bdm.o ocd.o ppc-sysv-tdep.o solib.o solib-svr4.o
TM_FILE= tm-ppcle-eabi.h
# Target: PowerPC running eabi in little endian mode under the simulator
-TDEPFILES= rs6000-tdep.o monitor.o dsrec.o ppcbug-rom.o ppc-bdm.o ocd.o ppc-linux-tdep.o solib.o solib-svr4.o
+TDEPFILES= rs6000-tdep.o monitor.o dsrec.o ppcbug-rom.o ppc-bdm.o ocd.o ppc-sysv-tdep.o solib.o solib-svr4.o
TM_FILE= tm-ppcle-eabi.h
SIM_OBS = remote-sim.o
# Target: Powerpc running VxWorks
-TDEPFILES= rs6000-tdep.o ppc-linux-tdep.o solib.o solib-svr4.o
+TDEPFILES= rs6000-tdep.o ppc-sysv-tdep.o solib.o solib-svr4.o
TM_FILE= tm-vxworks.h
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
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);
+}
--- /dev/null
+/* Target-dependent code for PowerPC systems using the SVR4 ABI
+ for GDB, the GNU debugger.
+
+ Copyright 2000, 2001, 2002 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdbcore.h"
+#include "inferior.h"
+#include "regcache.h"
+#include "value.h"
+
+#include "ppc-tdep.h"
+
+/* 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;
+}
+
+/* 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);
+}
#ifndef PPC_TDEP_H
#define PPC_TDEP_H
+#include "osabi.h"
+
struct frame_info;
struct value;
struct gdbarch_tdep
{
int wordsize; /* size in bytes of fixed-point word */
- int osabi; /* OS / ABI from ELF header */
+ enum gdb_osabi osabi; /* OS / ABI from ELF header */
int *regoff; /* byte offsets in register arrays */
const struct reg *regs; /* from current variant */
int ppc_gp0_regnum; /* GPR register 0 */
#include "defs.h"
#include "inferior.h"
-#include "gdbcore.h"
-#include "regcache.h"
#include "ppc-tdep.h"
#include "ppcnbsd-tdep.h"
return NULL;
}
-
-
-
-\f
-static void
-process_note_abi_tag_sections (bfd *abfd, asection *sect, void *obj)
-{
- int *os_ident_ptr = obj;
- const char *name;
- unsigned int sectsize;
-
- name = bfd_get_section_name (abfd, sect);
- sectsize = bfd_section_size (abfd, sect);
- if (strcmp (name, ".note.ABI-tag") == 0 && sectsize > 0)
- {
- unsigned int name_length, data_length, note_type;
- char *note = alloca (sectsize);
-
- bfd_get_section_contents (abfd, sect, note,
- (file_ptr) 0, (bfd_size_type) sectsize);
-
- name_length = bfd_h_get_32 (abfd, note);
- data_length = bfd_h_get_32 (abfd, note + 4);
- note_type = bfd_h_get_32 (abfd, note + 8);
-
- if (name_length == 4 && data_length == 16 && note_type == 1
- && strcmp (note + 12, "GNU") == 0)
- {
- int os_number = bfd_h_get_32 (abfd, note + 16);
-
- /* The case numbers are from abi-tags in glibc */
- switch (os_number)
- {
- case 0 :
- *os_ident_ptr = ELFOSABI_LINUX;
- break;
- case 1 :
- *os_ident_ptr = ELFOSABI_HURD;
- break;
- case 2 :
- *os_ident_ptr = ELFOSABI_SOLARIS;
- break;
- default :
- internal_error (__FILE__, __LINE__,
- "process_note_abi_sections: unknown OS number %d",
- os_number);
- break;
- }
- }
- }
-}
-
-/* Return one of the ELFOSABI_ constants for BFDs representing ELF
- executables. If it's not an ELF executable or if the OS/ABI couldn't
- be determined, simply return -1. */
-
-static int
-get_elfosabi (bfd *abfd)
-{
- int elfosabi = -1;
-
- if (abfd != NULL && bfd_get_flavour (abfd) == bfd_target_elf_flavour)
- {
- elfosabi = elf_elfheader (abfd)->e_ident[EI_OSABI];
-
- /* When elfosabi is 0 (ELFOSABI_NONE), this is supposed to indicate
- that we're on a SYSV system. However, GNU/Linux uses a note section
- to record OS/ABI info, but leaves e_ident[EI_OSABI] zero. So we
- have to check the note sections too. */
- if (elfosabi == 0)
- {
- bfd_map_over_sections (abfd,
- process_note_abi_tag_sections,
- &elfosabi);
- }
- }
-
- return elfosabi;
-}
-
\f
-
/* Initialize the current architecture based on INFO. If possible, re-use an
architecture from ARCHES, which is a list of architectures already created
during this debugging session.
enum bfd_architecture arch;
unsigned long mach;
bfd abfd;
- int osabi, sysv_abi;
+ int sysv_abi;
+ enum gdb_osabi osabi = GDB_OSABI_UNKNOWN;
gdbarch_print_insn_ftype *print_insn;
from_xcoff_exec = info.abfd && info.abfd->format == bfd_object &&
sysv_abi = info.abfd && bfd_get_flavour (info.abfd) == bfd_target_elf_flavour;
- osabi = get_elfosabi (info.abfd);
+ if (info.abfd)
+ osabi = gdbarch_lookup_osabi (info.abfd);
/* Check word size. If INFO is from a binary file, infer it from
that, else choose a likely default. */
/* Not sure on this. FIXMEmgo */
set_gdbarch_frame_args_skip (gdbarch, 8);
- /* 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. */
if (sysv_abi)
- {
- if (osabi == ELFOSABI_LINUX
- || osabi == ELFOSABI_NETBSD
- || osabi == ELFOSABI_FREEBSD)
- set_gdbarch_use_struct_convention (gdbarch,
- ppc_sysv_abi_broken_use_struct_convention);
- else
- set_gdbarch_use_struct_convention (gdbarch,
- ppc_sysv_abi_use_struct_convention);
- }
+ set_gdbarch_use_struct_convention (gdbarch,
+ ppc_sysv_abi_use_struct_convention);
else
- {
- set_gdbarch_use_struct_convention (gdbarch,
- generic_use_struct_convention);
- }
+ set_gdbarch_use_struct_convention (gdbarch,
+ generic_use_struct_convention);
set_gdbarch_frame_chain_valid (gdbarch, file_frame_chain_valid);
- /* Note: kevinb/2002-04-12: See note above regarding *_push_arguments().
- The same remarks hold for the methods below. */
- if (osabi == ELFOSABI_LINUX && wordsize == 4)
- {
- 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);
- }
- else
- {
- set_gdbarch_frameless_function_invocation (gdbarch,
- rs6000_frameless_function_invocation);
- set_gdbarch_frame_chain (gdbarch, rs6000_frame_chain);
- set_gdbarch_frame_saved_pc (gdbarch, rs6000_frame_saved_pc);
- set_gdbarch_frame_init_saved_regs (gdbarch, rs6000_frame_init_saved_regs);
- set_gdbarch_init_extra_frame_info (gdbarch, rs6000_init_extra_frame_info);
- }
+ set_gdbarch_frameless_function_invocation (gdbarch,
+ rs6000_frameless_function_invocation);
+ set_gdbarch_frame_chain (gdbarch, rs6000_frame_chain);
+ set_gdbarch_frame_saved_pc (gdbarch, rs6000_frame_saved_pc);
+
+ set_gdbarch_frame_init_saved_regs (gdbarch, rs6000_frame_init_saved_regs);
+ set_gdbarch_init_extra_frame_info (gdbarch, rs6000_init_extra_frame_info);
+
if (!sysv_abi)
{
/* Handle RS/6000 function pointers (which are really function
now that the C compiler delays popping them. */
set_gdbarch_frame_num_args (gdbarch, frame_num_args_unknown);
+ /* Hook in ABI-specific overrides, if they have been registered. */
+ gdbarch_init_osabi (info, gdbarch, osabi);
+
return gdbarch;
}
+static void
+rs6000_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+
+ if (tdep == NULL)
+ return;
+
+ fprintf_unfiltered (file, "rs6000_dump_tdep: OS ABI = %s\n",
+ gdbarch_osabi_name (tdep->osabi));
+}
+
static struct cmd_list_element *info_powerpc_cmdlist = NULL;
static void
void
_initialize_rs6000_tdep (void)
{
- register_gdbarch_init (bfd_arch_rs6000, rs6000_gdbarch_init);
- register_gdbarch_init (bfd_arch_powerpc, rs6000_gdbarch_init);
+ gdbarch_register (bfd_arch_rs6000, rs6000_gdbarch_init, rs6000_dump_tdep);
+ gdbarch_register (bfd_arch_powerpc, rs6000_gdbarch_init, rs6000_dump_tdep);
/* Add root prefix command for "info powerpc" commands */
add_prefix_cmd ("powerpc", class_info, rs6000_info_powerpc_command,
add_cmd ("altivec", class_info, rs6000_altivec_registers_info,
"Display the contents of the AltiVec registers.",
&info_powerpc_cmdlist);
-
}