* config/sparc/tm-sp64.h (CALL_DUMMY): Store and retrieve
%o0-%o5 as 64-bit values; compensate for stack bias. (USE_STRUCT_CONVENTION): We only pass pointers to structs if they're larger than 32 bytes. (REG_STRUCT_HAS_ADDR): Ditto. * sparc-tdep.c (sparc_init_extra_frame_info): Use read_sp() instead of read_register. If the target is a sparc64 and the frame pointer is odd, compensate for the stack bias. (get_saved_register): Use read_sp(). (DUMMY_STACK_REG_BUF_SIZE): Use FP_REGISTER_BYTES. (sparc_push_dummy_frame): Use read_sp()/write_sp(). On sparc64, save the PC, NPC, CCR, FSR, FPRS, Y and ASI registers. (sparc_frame_find_saved_regs): Use read_sp(). Read the PC, NPC, CCR, FSR, FPRS, Y and ASI registers from the frame, if it's a dummy frame. (sparc_pop_frame): Use write_sp(). If the target is a sparc64 and the FP is odd, compensate for stack bias. (sparc_store_return_value): Right-justify the return value before writing it to %o0. (sparc_fix_call_dummy): Don't NOP out part of the call dummy on sparc64. (sparc64_read_sp, sparc64_read_fp, sparc64_write_sp, sparc64_write_fp, sp64_push_arguments, sparc64_extract_return_value): New functions to support the sparc64 ABI. * dwarfread.c (handle_producer): Set processing_gcc_compilation to the right version number. * dwarf2read.c (read_file_scope): Assume we're processing GCC2 output.
This commit is contained in:
parent
d67094c621
commit
1e9c814fb9
|
@ -1,8 +1,9 @@
|
|||
/* Target machine sub-parameters for SPARC64, for GDB, the GNU debugger.
|
||||
This is included by other tm-*.h files to define SPARC64 cpu-related info.
|
||||
Copyright 1994, 1995, 1996 Free Software Foundation, Inc.
|
||||
Copyright 1994, 1995, 1996, 1998 Free Software Foundation, Inc.
|
||||
This is (obviously) based on the SPARC Vn (n<9) port.
|
||||
Contributed by Doug Evans (dje@cygnus.com).
|
||||
Further modified by Bob Manson (manson@cygnus.com).
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
|
@ -22,6 +23,80 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
|||
|
||||
#define GDB_TARGET_IS_SPARC64
|
||||
|
||||
#ifdef __STDC__
|
||||
struct value;
|
||||
#endif
|
||||
|
||||
/* Eeeew. Ok, we have to assume (for now) that the processor really is
|
||||
in sparc64 mode. While this is the same instruction sequence as
|
||||
on the Sparc, the stack frames are offset by +2047 (and the arguments
|
||||
are 8 bytes instead of 4). */
|
||||
/* Instructions are:
|
||||
std %f10, [ %fp + 0x7a7 ]
|
||||
std %f8, [ %fp + 0x79f ]
|
||||
std %f6, [ %fp + 0x797 ]
|
||||
std %f4, [ %fp + 0x78f ]
|
||||
std %f2, [ %fp + 0x787 ]
|
||||
std %f0, [ %fp + 0x77f ]
|
||||
std %g6, [ %fp + 0x777 ]
|
||||
std %g4, [ %fp + 0x76f ]
|
||||
std %g2, [ %fp + 0x767 ]
|
||||
std %g0, [ %fp + 0x75f ]
|
||||
std %fp, [ %fp + 0x757 ]
|
||||
std %i4, [ %fp + 0x74f ]
|
||||
std %i2, [ %fp + 0x747 ]
|
||||
std %i0, [ %fp + 0x73f ]
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
rd %tbr, %o0
|
||||
st %o0, [ %fp + 0x72b ]
|
||||
rd %tpc, %o0
|
||||
st %o0, [ %fp + 0x727 ]
|
||||
rd %psr, %o0
|
||||
st %o0, [ %fp + 0x723 ]
|
||||
rd %y, %o0
|
||||
st %o0, [ %fp + 0x71f ]
|
||||
ldx [ %sp + 0x8a7 ], %o5
|
||||
ldx [ %sp + 0x89f ], %o4
|
||||
ldx [ %sp + 0x897 ], %o3
|
||||
ldx [ %sp + 0x88f ], %o2
|
||||
ldx [ %sp + 0x887 ], %o1
|
||||
call %g0
|
||||
ldx [ %sp + 0x87f ], %o0
|
||||
nop
|
||||
ta 1
|
||||
nop
|
||||
nop
|
||||
*/
|
||||
|
||||
#define CALL_DUMMY { 0x9de3bec0fd3fa7f7LL, 0xf93fa7eff53fa7e7LL,\
|
||||
0xf13fa7dfed3fa7d7LL, 0xe93fa7cfe53fa7c7LL,\
|
||||
0xe13fa7bfdd3fa7b7LL, 0xd93fa7afd53fa7a7LL,\
|
||||
0xd13fa79fcd3fa797LL, 0xc93fa78fc53fa787LL,\
|
||||
0xc13fa77fcc3fa777LL, 0xc83fa76fc43fa767LL,\
|
||||
0xc03fa75ffc3fa757LL, 0xf83fa74ff43fa747LL,\
|
||||
0xf03fa73f01000000LL, 0x0100000001000000LL,\
|
||||
0x0100000091580000LL, 0xd027a72b93500000LL,\
|
||||
0xd027a72791480000LL, 0xd027a72391400000LL,\
|
||||
0xd027a71fda5ba8a7LL, 0xd85ba89fd65ba897LL,\
|
||||
0xd45ba88fd25ba887LL, 0x9fc02000d05ba87fLL,\
|
||||
0x0100000091d02001LL, 0x0100000001000000LL }
|
||||
|
||||
|
||||
/* 128 is to reserve space to write the %i/%l registers that will be restored
|
||||
when we resume. */
|
||||
#define CALL_DUMMY_STACK_ADJUST 128
|
||||
|
||||
#define CALL_DUMMY_LENGTH 192
|
||||
|
||||
#define CALL_DUMMY_START_OFFSET 148
|
||||
|
||||
#define CALL_DUMMY_CALL_OFFSET (CALL_DUMMY_START_OFFSET + (5 * 4))
|
||||
|
||||
#define CALL_DUMMY_BREAKPOINT_OFFSET (CALL_DUMMY_START_OFFSET + (8 * 4))
|
||||
|
||||
#include "sparc/tm-sparc.h"
|
||||
|
||||
/* Stack must be aligned on 128-bit boundaries when synthesizing
|
||||
|
@ -210,6 +285,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
|||
#undef TARGET_PTR_BIT
|
||||
#define TARGET_PTR_BIT 64
|
||||
|
||||
/* Longs are 64 bits. */
|
||||
#undef TARGET_LONG_BIT
|
||||
#define TARGET_LONG_BIT 64
|
||||
|
||||
#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
|
||||
|
@ -221,10 +303,16 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
|||
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, all structs are returned via a pointer. */
|
||||
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) 1
|
||||
#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. */
|
||||
|
@ -281,3 +369,26 @@ 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) (sp = 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));
|
||||
|
|
|
@ -251,7 +251,8 @@ extern CORE_ADDR sparc_pc_adjust PARAMS ((CORE_ADDR));
|
|||
#define CANNOT_STORE_REGISTER(regno) ((regno) == G0_REGNUM)
|
||||
|
||||
/* Store the address of the place in which to copy the structure the
|
||||
subroutine will return. This is called from call_function_by_hand. */
|
||||
subroutine will return. This is called from call_function_by_hand.
|
||||
The ultimate mystery is, tho, what is the value "16"? */
|
||||
|
||||
#define STORE_STRUCT_RETURN(ADDR, SP) \
|
||||
{ char val[4]; \
|
||||
|
@ -466,6 +467,7 @@ extern CORE_ADDR sparc_frame_saved_pc PARAMS ((struct frame_info *));
|
|||
|
||||
void sparc_push_dummy_frame PARAMS ((void)), sparc_pop_frame PARAMS ((void));
|
||||
|
||||
#ifndef CALL_DUMMY
|
||||
/* This sequence of words is the instructions
|
||||
|
||||
0: mov %g1, %fp
|
||||
|
@ -515,6 +517,7 @@ void sparc_push_dummy_frame PARAMS ((void)), sparc_pop_frame PARAMS ((void));
|
|||
|
||||
#define CALL_DUMMY_STACK_ADJUST 68
|
||||
|
||||
#endif
|
||||
/* Insert the specified number of args and function address
|
||||
into a call sequence of the above form stored at DUMMYNAME. */
|
||||
|
||||
|
|
|
@ -1513,6 +1513,8 @@ read_file_scope (die, objfile)
|
|||
set_cu_language (DW_UNSND (attr));
|
||||
}
|
||||
|
||||
/* We assume that we're processing GCC output. */
|
||||
processing_gcc_compilation = 2;
|
||||
#if 0
|
||||
/* FIXME:Do something here. */
|
||||
if (dip->at_producer != NULL)
|
||||
|
|
|
@ -1902,10 +1902,17 @@ handle_producer (producer)
|
|||
/* If this compilation unit was compiled with g++ or gcc, then set the
|
||||
processing_gcc_compilation flag. */
|
||||
|
||||
if (STREQN (producer, GCC_PRODUCER, strlen (GCC_PRODUCER)))
|
||||
{
|
||||
char version = producer[strlen (GCC_PRODUCER)];
|
||||
processing_gcc_compilation = (version == '2' ? 2 : 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
processing_gcc_compilation =
|
||||
STREQN (producer, GPLUS_PRODUCER, strlen (GPLUS_PRODUCER))
|
||||
|| STREQN (producer, CHILL_PRODUCER, strlen (CHILL_PRODUCER))
|
||||
|| STREQN (producer, GCC_PRODUCER, strlen (GCC_PRODUCER));
|
||||
|| STREQN (producer, CHILL_PRODUCER, strlen (CHILL_PRODUCER));
|
||||
}
|
||||
|
||||
/* Select a demangling style if we can identify the producer and if
|
||||
the current style is auto. We leave the current style alone if it
|
||||
|
|
Loading…
Reference in New Issue