mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-12-27 01:28:46 +00:00
* 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.
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user