forked from Imagelibrary/binutils-gdb
2000-05-10 Michael Snyder <msnyder@seadog.cygnus.com>
Make Sparc a Multi-Arch target. Discard PARAMS macro (require ANSI). * sparc-tdep.c: include arch-utils.h. (SPARC_HAS_FPU, FP_REGISTER_BYTES, FP_MAX_REG NUM, SPARC_INTREG_SIZE, DUMMY_REG_SAVE_OFFSET): provide multi-arch-compatible definitions. (GDB_TARGET_IS_SPARC64): make into a runtime test. (struct frame_extra_info): Define, use instead of the macro. (Many places): Use alloca instead of statically allocated buffers that depend on a multi-arch variable such as MAX_REGISTER_RAW_SIZE. (sparc_extract_struct_value_address): Accept a pointer arg instead of an array sized by REGISTER_BYTES. (examine_prologue): Accept a pointer to an array of CORE_ADDR, instead of the defunct struct frame_saved_regs. Recognize new Sparc64 store instructions as part of the prologue. Ignore the destination of a frame store when parsing the prologue (so long as it's on the stack). (sparc_push_dummy_frame): Fix incorrect buffer offset for PSTATE. (sparc_frame_find_saved_regs): Accept a ptr to an array of CORE_ADDR instead of the defunct struct frame_saved_regs. (supply_gregset): Discard unnecessary 'zerobuf': just send NULL to supply_register. Provide 4-byte offset to compensate for diff between size of the prgreg_t elements on a 64-bit host and size of the registers for a 32-bit target. Fill all inaccessible regs with zero so they won't keep being requested again and again. (fill_gregset): Handle 32/64 size difference between registers and prgreg_t. Handle as many new 64-bit regs as possible. (supply_fpregset, fill_fpregset): Attempt to handle 64-bit world. (sparc_push_arguments): Rename to sparc32_push_arguments. Copy arguments into registers as well as onto stack, so that the CALL_DUMMY (code pushed onto the target stack) is not required. (sparc_extract_return_value): Rename to sparc32_extract_return_value. (sparc_store_return_value): Use memset instead of bzero. Use write_register_gen instead of write_register_bytes. (sparclet_store_return_value): New function. (_initialize_sparc_tdep): Call register_gdbarch_init to activate the gdbarch multi-architecture system. (sp64_push_arguments): Rename to sparc64_push_arguments. Extend to store arguments in general registers as well as on stack. (sparc64_extract_return_value): Rename to sp64_extract_return_value. Use as a private function, to be called by the new external function sparc64_extract_return_value. (sparclet_extract_return_value): New function. (sparc32_stack_align, sparc64_stack_align, sparc32_register_name, sparc64_register_name, sparc_print_extra_frame_info, sparclite_register_name, sparclet_register_name, sparc_push_return_address, sparc64_use_struct_convention, sparc32_store_struct_return, sparc64_store_struct_return, sparc32_register_virtual_type, sparc64_register_virtual_type, sparc32_register_size, sparc64_register_size, sparc32_register_byte, sparc64_register_byte, sparc_gdbarch_skip_prologue, sparc_convert_to_virtual, sparc_convert_to_raw, sparc_frame_init_saved_regs, sparc_frame_address, sparc_gdbarch_fix_call_dummy, sparc_coerce_float_to_double, sparc_call_dummy_address, sparc_y_regnum, sparc_reg_struct_has_addr, sparc_intreg_size, sparc_return_value_on_stack): New functions supporting multi-arch. (sparc_gdbarch_init): New function; initialize multi-arch. (struct gdbarch_tdep): Define, use for private multi-arch data. * config/sparc/tm-sparc.h: Move definitions around, enclose with #ifdef GDB_MULTI_ARCH tests, provide some multi-arch alternate definitions. Add enums for register names, to help debugging gdb. This header file must work for non-multi-arch and for multi-arch. * config/sparc/tm-sp64.h: Add GDB_MULTI_ARCH configuration. Also add AT_ENTRY_POINT definitions for CALL_DUMMY, for non-multi-arch case. Define GDB_MULTI_ARCH. * config/sparc/tm-sparclet.h: Add GDB_MULTI_ARCH configuration. Do not define GDB_MULTI_ARCH (bfd does not correctly identify target). * config/sparc/tm-sparclite.h: Ditto. * config/sparc/tm-sun4sol2.h: Define GDB_MULTI_ARCH. * sparclet-rom.c (sparclet_regnames): Initialize explicitly, to avoid using deprecated REGISTER_NAMES macro. * Makefile.in: Let sparc-tdep.c depend on arch-utils.h.
This commit is contained in:
@@ -22,9 +22,13 @@
|
||||
Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#define GDB_TARGET_IS_SPARC64
|
||||
#define GDB_MULTI_ARCH 2
|
||||
|
||||
struct value;
|
||||
#ifndef GDB_TARGET_IS_SPARC64
|
||||
#define GDB_TARGET_IS_SPARC64 1
|
||||
#endif
|
||||
|
||||
#include "sparc/tm-sparc.h"
|
||||
|
||||
/* Eeeew. Ok, we have to assume (for now) that the processor really is
|
||||
in sparc64 mode. While this is the same instruction sequence as
|
||||
@@ -70,6 +74,57 @@ struct value;
|
||||
nop
|
||||
*/
|
||||
|
||||
#if !defined (GDB_MULTI_ARCH) || (GDB_MULTI_ARCH == 0)
|
||||
/*
|
||||
* The following defines must go away for MULTI_ARCH.
|
||||
*/
|
||||
|
||||
#ifndef DO_CALL_DUMMY_ON_STACK
|
||||
|
||||
/*
|
||||
* These defines will suffice for the AT_ENTRY_POINT call dummy method.
|
||||
*/
|
||||
|
||||
#undef CALL_DUMMY
|
||||
#define CALL_DUMMY {0}
|
||||
#undef CALL_DUMMY_LENGTH
|
||||
#define CALL_DUMMY_LENGTH 0
|
||||
#undef CALL_DUMMY_CALL_OFFSET
|
||||
#define CALL_DUMMY_CALL_OFFSET 0
|
||||
#undef CALL_DUMMY_START_OFFSET
|
||||
#define CALL_DUMMY_START_OFFSET 0
|
||||
#undef CALL_DUMMY_BREAKPOINT_OFFSET
|
||||
#define CALL_DUMMY_BREAKPOINT_OFFSET 0
|
||||
#undef CALL_DUMMY_BREAKPOINT_OFFSET_P
|
||||
#define CALL_DUMMY_BREAKPOINT_OFFSET_P 1
|
||||
#undef CALL_DUMMY_LOCATION
|
||||
#define CALL_DUMMY_LOCATION AT_ENTRY_POINT
|
||||
#undef CALL_DUMMY_STACK_ADJUST
|
||||
#define CALL_DUMMY_STACK_ADJUST 128
|
||||
#undef SIZEOF_CALL_DUMMY_WORDS
|
||||
#define SIZEOF_CALL_DUMMY_WORDS 0
|
||||
#undef CALL_DUMMY_ADDRESS
|
||||
#define CALL_DUMMY_ADDRESS() entry_point_address()
|
||||
#undef FIX_CALL_DUMMY
|
||||
#define FIX_CALL_DUMMY(DUMMYNAME, PC, FUN, NARGS, ARGS, TYPE, GCC_P)
|
||||
#undef PUSH_RETURN_ADDRESS
|
||||
#define PUSH_RETURN_ADDRESS(PC, SP) sparc_at_entry_push_return_address (PC, SP)
|
||||
extern CORE_ADDR
|
||||
sparc_at_entry_push_return_address (CORE_ADDR pc, CORE_ADDR sp);
|
||||
|
||||
#undef STORE_STRUCT_RETURN
|
||||
#define STORE_STRUCT_RETURN(ADDR, SP) \
|
||||
sparc_at_entry_store_struct_return (ADDR, SP)
|
||||
extern void
|
||||
sparc_at_entry_store_struct_return (CORE_ADDR addr, CORE_ADDR sp);
|
||||
|
||||
|
||||
#else
|
||||
/*
|
||||
* Old call dummy method, with CALL_DUMMY on the stack.
|
||||
*/
|
||||
|
||||
#undef CALL_DUMMY
|
||||
#define CALL_DUMMY { 0x9de3bec0fd3fa7f7LL, 0xf93fa7eff53fa7e7LL,\
|
||||
0xf13fa7dfed3fa7d7LL, 0xe93fa7cfe53fa7c7LL,\
|
||||
0xe13fa7bfdd3fa7b7LL, 0xd93fa7afd53fa7a7LL,\
|
||||
@@ -86,17 +141,83 @@ struct value;
|
||||
|
||||
/* 128 is to reserve space to write the %i/%l registers that will be restored
|
||||
when we resume. */
|
||||
#undef CALL_DUMMY_STACK_ADJUST
|
||||
#define CALL_DUMMY_STACK_ADJUST 128
|
||||
|
||||
/* Size of the call dummy in bytes. */
|
||||
#undef CALL_DUMMY_LENGTH
|
||||
#define CALL_DUMMY_LENGTH 192
|
||||
|
||||
/* Offset within CALL_DUMMY of the 'call' instruction. */
|
||||
#undef CALL_DUMMY_START_OFFSET
|
||||
#define CALL_DUMMY_START_OFFSET 148
|
||||
|
||||
/* Offset within CALL_DUMMY of the 'call' instruction. */
|
||||
#undef CALL_DUMMY_CALL_OFFSET
|
||||
#define CALL_DUMMY_CALL_OFFSET (CALL_DUMMY_START_OFFSET + (5 * 4))
|
||||
|
||||
/* Offset within CALL_DUMMY of the 'ta 1' instruction. */
|
||||
#undef CALL_DUMMY_BREAKPOINT_OFFSET
|
||||
#define CALL_DUMMY_BREAKPOINT_OFFSET (CALL_DUMMY_START_OFFSET + (8 * 4))
|
||||
|
||||
#include "sparc/tm-sparc.h"
|
||||
/* Let's GDB know that it can make a call_dummy breakpoint. */
|
||||
#undef CALL_DUMMY_BREAKPOINT_OFFSET_P
|
||||
#define CALL_DUMMY_BREAKPOINT_OFFSET_P 1
|
||||
|
||||
/* Call dummy will be located on the stack. */
|
||||
#undef CALL_DUMMY_LOCATION
|
||||
#define CALL_DUMMY_LOCATION ON_STACK
|
||||
|
||||
/* Insert the function address into the call dummy. */
|
||||
#undef FIX_CALL_DUMMY
|
||||
#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
|
||||
sparc_fix_call_dummy (dummyname, pc, fun, type, gcc_p)
|
||||
void sparc_fix_call_dummy PARAMS ((char *dummy, CORE_ADDR pc, CORE_ADDR fun,
|
||||
struct type * value_type, int using_gcc));
|
||||
|
||||
|
||||
/* The remainder of these will accept the default definition. */
|
||||
#undef SIZEOF_CALL_DUMMY_WORDS
|
||||
#undef PUSH_RETURN_ADDRESS
|
||||
#undef CALL_DUMMY_ADDRESS
|
||||
#undef STORE_STRUCT_RETURN
|
||||
|
||||
#endif
|
||||
|
||||
/* Does the specified function use the "struct returning" convention
|
||||
or the "value returning" convention? The "value returning" convention
|
||||
almost invariably returns the entire value in registers. The
|
||||
"struct returning" convention often returns the entire value in
|
||||
memory, and passes a pointer (out of or into the function) saying
|
||||
where the value (is or should go).
|
||||
|
||||
Since this sometimes depends on whether it was compiled with GCC,
|
||||
this is also an argument. This is used in call_function to build a
|
||||
stack, and in value_being_returned to print return values.
|
||||
|
||||
On Sparc64, we only pass pointers to structs if they're larger then
|
||||
32 bytes. Otherwise they're stored in %o0-%o3 (floating-point
|
||||
values go into %fp0-%fp3). */
|
||||
|
||||
#undef USE_STRUCT_CONVENTION
|
||||
#define USE_STRUCT_CONVENTION(gcc_p, type) (TYPE_LENGTH (type) > 32)
|
||||
|
||||
CORE_ADDR sparc64_push_arguments PARAMS ((int,
|
||||
struct value **,
|
||||
CORE_ADDR,
|
||||
int,
|
||||
CORE_ADDR));
|
||||
#undef PUSH_ARGUMENTS
|
||||
#define PUSH_ARGUMENTS(A,B,C,D,E) \
|
||||
(sparc64_push_arguments ((A), (B), (C), (D), (E)))
|
||||
|
||||
/* Store the address of the place in which to copy the structure the
|
||||
subroutine will return. This is called from call_function. */
|
||||
/* FIXME: V9 uses %o0 for this. */
|
||||
|
||||
#undef STORE_STRUCT_RETURN
|
||||
#define STORE_STRUCT_RETURN(ADDR, SP) \
|
||||
{ target_write_memory ((SP)+(16*8), (char *)&(ADDR), 8); }
|
||||
|
||||
/* Stack must be aligned on 128-bit boundaries when synthesizing
|
||||
function calls. */
|
||||
@@ -104,11 +225,6 @@ struct value;
|
||||
#undef STACK_ALIGN
|
||||
#define STACK_ALIGN(ADDR) (((ADDR) + 15 ) & -16)
|
||||
|
||||
/* Number of machine registers. */
|
||||
|
||||
#undef NUM_REGS
|
||||
#define NUM_REGS 125
|
||||
|
||||
/* Initializer for an array of names of registers.
|
||||
There should be NUM_REGS strings in this initializer. */
|
||||
/* Some of these registers are only accessible from priviledged mode.
|
||||
@@ -148,6 +264,25 @@ struct value;
|
||||
"icc", "xcc", "fcc0", "fcc1", "fcc2", "fcc3" \
|
||||
}
|
||||
|
||||
#undef REG_STRUCT_HAS_ADDR
|
||||
#define REG_STRUCT_HAS_ADDR(gcc_p,type) (TYPE_LENGTH (type) > 32)
|
||||
|
||||
extern CORE_ADDR sparc64_read_sp ();
|
||||
extern CORE_ADDR sparc64_read_fp ();
|
||||
extern void sparc64_write_sp PARAMS ((CORE_ADDR));
|
||||
extern void sparc64_write_fp PARAMS ((CORE_ADDR));
|
||||
|
||||
#define TARGET_READ_SP() (sparc64_read_sp ())
|
||||
#define TARGET_READ_FP() (sparc64_read_fp ())
|
||||
#define TARGET_WRITE_SP(X) (sparc64_write_sp (X))
|
||||
#define TARGET_WRITE_FP(X) (sparc64_write_fp (X))
|
||||
|
||||
#undef EXTRACT_RETURN_VALUE
|
||||
#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
|
||||
sp64_extract_return_value(TYPE, REGBUF, VALBUF, 0)
|
||||
extern void
|
||||
sp64_extract_return_value PARAMS ((struct type *, char[], char *, int));
|
||||
|
||||
/* Register numbers of various important registers.
|
||||
Note that some of these values are "real" register numbers,
|
||||
and correspond to the general registers of the machine,
|
||||
@@ -155,7 +290,8 @@ struct value;
|
||||
to be actual register numbers as far as the user is concerned
|
||||
but do serve to get the desired values when passed to read_register. */
|
||||
|
||||
#if 0 /* defined in tm-sparc.h, replicated for doc purposes */
|
||||
#if 0 /* defined in tm-sparc.h, replicated
|
||||
for doc purposes */
|
||||
#define G0_REGNUM 0 /* %g0 */
|
||||
#define G1_REGNUM 1 /* %g1 */
|
||||
#define O0_REGNUM 8 /* %o0 */
|
||||
@@ -172,7 +308,7 @@ struct value;
|
||||
#define FP0_REGNUM 32 /* Floating point register 0 */
|
||||
#endif
|
||||
|
||||
#define FP_MAX_REGNUM 80 /* 1 + last fp reg number */
|
||||
/*#define FP_MAX_REGNUM 80*/ /* 1 + last fp reg number */
|
||||
|
||||
/* #undef v8 misc. regs */
|
||||
|
||||
@@ -187,7 +323,8 @@ struct value;
|
||||
|
||||
/* v9 misc. and priv. regs */
|
||||
|
||||
#define C0_REGNUM FP_MAX_REGNUM /* Start of control registers */
|
||||
#define C0_REGNUM 80 /* Start of control registers */
|
||||
|
||||
#define PC_REGNUM (C0_REGNUM + 0) /* Current PC */
|
||||
#define NPC_REGNUM (C0_REGNUM + 1) /* Next PC */
|
||||
#define CCR_REGNUM (C0_REGNUM + 2) /* Condition Code Register (%xcc,%icc) */
|
||||
@@ -220,6 +357,11 @@ struct value;
|
||||
#define FCC2_REGNUM (C0_REGNUM + 43) /* fp cc reg 2 */
|
||||
#define FCC3_REGNUM (C0_REGNUM + 44) /* fp cc reg 3 */
|
||||
|
||||
/* Number of machine registers. */
|
||||
|
||||
#undef NUM_REGS
|
||||
#define NUM_REGS 125
|
||||
|
||||
/* Total amount of space needed to store our copies of the machine's
|
||||
register state, the array `registers'.
|
||||
Some of the registers aren't 64 bits, but it's a lot simpler just to assume
|
||||
@@ -291,40 +433,12 @@ struct value;
|
||||
#undef TARGET_LONG_LONG_BIT
|
||||
#define TARGET_LONG_LONG_BIT 64
|
||||
|
||||
/* Does the specified function use the "struct returning" convention
|
||||
or the "value returning" convention? The "value returning" convention
|
||||
almost invariably returns the entire value in registers. The
|
||||
"struct returning" convention often returns the entire value in
|
||||
memory, and passes a pointer (out of or into the function) saying
|
||||
where the value (is or should go).
|
||||
|
||||
Since this sometimes depends on whether it was compiled with GCC,
|
||||
this is also an argument. This is used in call_function to build a
|
||||
stack, and in value_being_returned to print return values.
|
||||
|
||||
On Sparc64, we only pass pointers to structs if they're larger then
|
||||
32 bytes. Otherwise they're stored in %o0-%o3 (floating-point
|
||||
values go into %fp0-%fp3). */
|
||||
|
||||
|
||||
#undef USE_STRUCT_CONVENTION
|
||||
#define USE_STRUCT_CONVENTION(gcc_p, type) (TYPE_LENGTH (type) > 32)
|
||||
|
||||
#undef REG_STRUCT_HAS_ADDR
|
||||
#define REG_STRUCT_HAS_ADDR(gcc_p,type) (TYPE_LENGTH (type) > 32)
|
||||
|
||||
/* Store the address of the place in which to copy the structure the
|
||||
subroutine will return. This is called from call_function. */
|
||||
/* FIXME: V9 uses %o0 for this. */
|
||||
|
||||
#undef STORE_STRUCT_RETURN
|
||||
#define STORE_STRUCT_RETURN(ADDR, SP) \
|
||||
{ target_write_memory ((SP)+(16*8), (char *)&(ADDR), 8); }
|
||||
|
||||
/* Return number of bytes at start of arglist that are not really args. */
|
||||
|
||||
#undef FRAME_ARGS_SKIP
|
||||
#define FRAME_ARGS_SKIP 136
|
||||
|
||||
#endif /* GDB_MULTI_ARCH */
|
||||
|
||||
/* Offsets into jmp_buf.
|
||||
FIXME: This was borrowed from the v8 stuff and will probably have to change
|
||||
@@ -342,36 +456,18 @@ struct value;
|
||||
#define JB_O0 7
|
||||
#define JB_WBCNT 8
|
||||
|
||||
/* Figure out where the longjmp will land. We expect that we have just entered
|
||||
longjmp and haven't yet setup the stack frame, so the args are still in the
|
||||
output regs. %o0 (O0_REGNUM) points at the jmp_buf structure from which we
|
||||
extract the pc (JB_PC) that we will land at. The pc is copied into ADDR.
|
||||
This routine returns true on success */
|
||||
/* Figure out where the longjmp will land. We expect that we have
|
||||
just entered longjmp and haven't yet setup the stack frame, so the
|
||||
args are still in the output regs. %o0 (O0_REGNUM) points at the
|
||||
jmp_buf structure from which we extract the pc (JB_PC) that we will
|
||||
land at. The pc is copied into ADDR. This routine returns true on
|
||||
success */
|
||||
|
||||
extern int
|
||||
get_longjmp_target PARAMS ((CORE_ADDR *));
|
||||
|
||||
#define GET_LONGJMP_TARGET(ADDR) get_longjmp_target(ADDR)
|
||||
|
||||
extern CORE_ADDR sparc64_read_sp ();
|
||||
extern CORE_ADDR sparc64_read_fp ();
|
||||
extern void sparc64_write_sp PARAMS ((CORE_ADDR));
|
||||
extern void sparc64_write_fp PARAMS ((CORE_ADDR));
|
||||
|
||||
#define TARGET_READ_SP() (sparc64_read_sp ())
|
||||
#define TARGET_READ_FP() (sparc64_read_fp ())
|
||||
#define TARGET_WRITE_SP(X) (sparc64_write_sp (X))
|
||||
#define TARGET_WRITE_FP(X) (sparc64_write_fp (X))
|
||||
|
||||
#undef TM_PRINT_INSN_MACH
|
||||
#define TM_PRINT_INSN_MACH bfd_mach_sparc_v9a
|
||||
|
||||
CORE_ADDR sp64_push_arguments PARAMS ((int, struct value **, CORE_ADDR, unsigned char, CORE_ADDR));
|
||||
#undef PUSH_ARGUMENTS
|
||||
#define PUSH_ARGUMENTS(A,B,C,D,E) (sp64_push_arguments ((A), (B), (C), (D), (E)))
|
||||
|
||||
#undef EXTRACT_RETURN_VALUE
|
||||
#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
|
||||
sparc64_extract_return_value(TYPE, REGBUF, VALBUF, 0)
|
||||
extern void
|
||||
sparc64_extract_return_value PARAMS ((struct type *, char[], char *, int));
|
||||
|
||||
Reference in New Issue
Block a user