/* Target-dependent code for the SPARC for GDB, the GNU debugger.
- Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997
- Free Software Foundation, Inc.
+ Copyright 1986, 1987, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
+ 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
This file is part of GDB.
#include "value.h"
#include "bfd.h"
#include "gdb_string.h"
+#include "regcache.h"
#ifdef USE_PROC_FS
#include <sys/procfs.h>
+/* Prototypes for supply_gregset etc. */
+#include "gregset.h"
#endif
#include "gdbcore.h"
such as sparc86x, instructions are always big-endian. */
static unsigned long
-fetch_instruction (pc)
- CORE_ADDR pc;
+fetch_instruction (CORE_ADDR pc)
{
unsigned long retval;
int i;
set up a simulated single-step, we undo our damage. */
void
-sparc_software_single_step (ignore, insert_breakpoints_p)
- enum target_signal ignore; /* pid, but we don't need it */
- int insert_breakpoints_p;
+sparc_software_single_step (enum target_signal ignore, /* pid, but we don't need it */
+ int insert_breakpoints_p)
{
branch_type br;
CORE_ADDR pc;
been stashed, since their exact position within the frame may vary. */
void
-sparc_init_extra_frame_info (fromleaf, fi)
- int fromleaf;
- struct frame_info *fi;
+sparc_init_extra_frame_info (int fromleaf, struct frame_info *fi)
{
char *name;
CORE_ADDR prologue_start, prologue_end;
negative number if a flat frame) to the sp. FIXME: Does not
handle large frames which will need more than one instruction
to adjust the sp. */
- insn = fetch_instruction (prologue_start, 4);
+ insn = fetch_instruction (prologue_start);
if (X_OP (insn) == 2 && X_RD (insn) == 14 && X_OP3 (insn) == 0
&& X_I (insn) && X_SIMM13 (insn) < 0)
{
}
CORE_ADDR
-sparc_frame_chain (frame)
- struct frame_info *frame;
+sparc_frame_chain (struct frame_info *frame)
{
/* Value that will cause FRAME_CHAIN_VALID to not worry about the chain
- value. If it realy is zero, we detect it later in
+ value. If it really is zero, we detect it later in
sparc_init_prev_frame. */
return (CORE_ADDR) 1;
}
CORE_ADDR
-sparc_extract_struct_value_address (regbuf)
- char *regbuf;
+sparc_extract_struct_value_address (char *regbuf)
{
return extract_address (regbuf + REGISTER_BYTE (O0_REGNUM),
REGISTER_RAW_SIZE (O0_REGNUM));
/* Find the pc saved in frame FRAME. */
CORE_ADDR
-sparc_frame_saved_pc (frame)
- struct frame_info *frame;
+sparc_frame_saved_pc (struct frame_info *frame)
{
char *buf;
CORE_ADDR addr;
difficulty. */
struct frame_info *
-setup_arbitrary_frame (argc, argv)
- int argc;
- CORE_ADDR *argv;
+setup_arbitrary_frame (int argc, CORE_ADDR *argv)
{
struct frame_info *frame;
frame = create_new_frame (argv[0], 0);
if (!frame)
- internal_error ("create_new_frame returned invalid frame");
+ internal_error (__FILE__, __LINE__,
+ "create_new_frame returned invalid frame");
frame->extra_info->bottom = argv[1];
frame->pc = FRAME_SAVED_PC (frame);
CORE_ADDR *);
static CORE_ADDR
-examine_prologue (start_pc, frameless_p, fi, saved_regs)
- CORE_ADDR start_pc;
- int frameless_p;
- struct frame_info *fi;
- CORE_ADDR *saved_regs;
+examine_prologue (CORE_ADDR start_pc, int frameless_p, struct frame_info *fi,
+ CORE_ADDR *saved_regs)
{
int insn;
int dest = -1;
}
CORE_ADDR
-sparc_skip_prologue (start_pc, frameless_p)
- CORE_ADDR start_pc;
- int frameless_p;
+sparc_skip_prologue (CORE_ADDR start_pc, int frameless_p)
{
return examine_prologue (start_pc, frameless_p, NULL, NULL);
}
This isn't static as it's used by remote-sa.sparc.c. */
static branch_type
-isbranch (instruction, addr, target)
- long instruction;
- CORE_ADDR addr, *target;
+isbranch (long instruction, CORE_ADDR addr, CORE_ADDR *target)
{
branch_type val = not_branch;
long int offset = 0; /* Must be signed for sign-extend. */
The argument RAW_BUFFER must point to aligned memory. */
void
-sparc_get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval)
- char *raw_buffer;
- int *optimized;
- CORE_ADDR *addrp;
- struct frame_info *frame;
- int regnum;
- enum lval_type *lval;
+sparc_get_saved_register (char *raw_buffer, int *optimized, CORE_ADDR *addrp,
+ struct frame_info *frame, int regnum,
+ enum lval_type *lval)
{
struct frame_info *frame1;
CORE_ADDR addr;
(DUMMY_STACK_REG_BUF_SIZE + DUMMY_REG_SAVE_OFFSET)
void
-sparc_push_dummy_frame ()
+sparc_push_dummy_frame (void)
{
CORE_ADDR sp, old_sp;
char *register_temp;
static void sparc_frame_find_saved_regs (struct frame_info *, CORE_ADDR *);
static void
-sparc_frame_find_saved_regs (fi, saved_regs_addr)
- struct frame_info *fi;
- CORE_ADDR *saved_regs_addr;
+sparc_frame_find_saved_regs (struct frame_info *fi, CORE_ADDR *saved_regs_addr)
{
register int regnum;
CORE_ADDR frame_addr = FRAME_FP (fi);
if (!fi)
- internal_error ("Bad frame info struct in FRAME_FIND_SAVED_REGS");
+ internal_error (__FILE__, __LINE__,
+ "Bad frame info struct in FRAME_FIND_SAVED_REGS");
memset (saved_regs_addr, 0, NUM_REGS * sizeof (CORE_ADDR));
/* Definitely see tm-sparc.h for more doc of the frame format here. */
void
-sparc_pop_frame ()
+sparc_pop_frame (void)
{
register struct frame_info *frame = get_current_frame ();
register CORE_ADDR pc;
a fake insn, step past it. */
CORE_ADDR
-sparc_pc_adjust (pc)
- CORE_ADDR pc;
+sparc_pc_adjust (CORE_ADDR pc)
{
unsigned long insn;
char buf[4];
by hand. */
CORE_ADDR
-sunos4_skip_trampoline_code (pc)
- CORE_ADDR pc;
+sunos4_skip_trampoline_code (CORE_ADDR pc)
{
unsigned long insn1;
char buf[4];
*/
/* *INDENT-ON* */
-
-
/* Given a pointer to a general register set in /proc format (gregset_t *),
unpack the register contents and supply them as gdb's idea of the current
register values. */
void
-supply_gregset (gregsetp)
- prgregset_t *gregsetp;
+supply_gregset (gdb_gregset_t *gregsetp)
{
prgreg_t *regp = (prgreg_t *) gregsetp;
int regi, offset = 0;
}
void
-fill_gregset (gregsetp, regno)
- prgregset_t *gregsetp;
- int regno;
+fill_gregset (gdb_gregset_t *gregsetp, int regno)
{
prgreg_t *regp = (prgreg_t *) gregsetp;
int regi, offset = 0;
idea of the current floating point register values. */
void
-supply_fpregset (fpregsetp)
- prfpregset_t *fpregsetp;
+supply_fpregset (gdb_fpregset_t *fpregsetp)
{
register int regi;
char *from;
/* This will probably need some changes for sparc64. */
void
-fill_fpregset (fpregsetp, regno)
- prfpregset_t *fpregsetp;
- int regno;
+fill_fpregset (gdb_fpregset_t *fpregsetp, int regno)
{
int regi;
char *to;
This routine returns true on success */
int
-get_longjmp_target (pc)
- CORE_ADDR *pc;
+get_longjmp_target (CORE_ADDR *pc)
{
CORE_ADDR jb_addr;
#define LONGJMP_TARGET_SIZE 4
related to C++ mangling, it is done for C too. */
char *
-sunpro_static_transform_name (name)
- char *name;
+sunpro_static_transform_name (char *name)
{
char *p;
if (name[0] == '$')
static void dump_ccreg (char *, int);
static void
-dump_ccreg (reg, val)
- char *reg;
- int val;
+dump_ccreg (char *reg, int val)
{
/* page 41 */
printf_unfiltered ("%s:%s,%s,%s,%s", reg,
}
static char *
-decode_asi (val)
- int val;
+decode_asi (int val)
{
/* page 72 */
switch (val)
/* FIXME: Would be nice if this did some fancy things for 32 bit sparc. */
void
-sparc_print_register_hook (regno)
- int regno;
+sparc_print_register_hook (int regno)
{
ULONGEST val;
}
\f
int
-gdb_print_insn_sparc (memaddr, info)
- bfd_vma memaddr;
- disassemble_info *info;
+gdb_print_insn_sparc (bfd_vma memaddr, disassemble_info *info)
{
/* It's necessary to override mach again because print_insn messes it up. */
info->mach = TARGET_ARCHITECTURE->mach;
args are also passed in registers o0 - o5. */
CORE_ADDR
-sparc32_push_arguments (nargs, args, sp, struct_return, struct_addr)
- int nargs;
- value_ptr *args;
- CORE_ADDR sp;
- int struct_return;
- CORE_ADDR struct_addr;
+sparc32_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
+ int struct_return, CORE_ADDR struct_addr)
{
int i, j, oregnum;
int accumulate_size = 0;
and sizes. */
for (i = 0, m_arg = sparc_args; i < nargs; i++, m_arg++)
{
- value_ptr arg = args[i];
+ struct value *arg = args[i];
struct type *arg_type = check_typedef (VALUE_TYPE (arg));
/* Cast argument to long if necessary as the compiler does it too. */
switch (TYPE_CODE (arg_type))
into VALBUF. */
void
-sparc32_extract_return_value (type, regbuf, valbuf)
- struct type *type;
- char *regbuf;
- char *valbuf;
+sparc32_extract_return_value (struct type *type, char *regbuf, char *valbuf)
{
int typelen = TYPE_LENGTH (type);
int regsize = REGISTER_RAW_SIZE (O0_REGNUM);
values are returned in register %o0. */
void
-sparc_store_return_value (type, valbuf)
- struct type *type;
- char *valbuf;
+sparc_store_return_value (struct type *type, char *valbuf)
{
int regno;
char *buffer;
has already been customized for a different function). */
void
-sparc_fix_call_dummy (dummy, pc, fun, value_type, using_gcc)
- char *dummy;
- CORE_ADDR pc;
- CORE_ADDR fun;
- struct type *value_type;
- int using_gcc;
+sparc_fix_call_dummy (char *dummy, CORE_ADDR pc, CORE_ADDR fun,
+ struct type *value_type, int using_gcc)
{
int i;
| (((fun - (pc + CALL_DUMMY_CALL_OFFSET)) >> 2)
& 0x3fffffff)));
- /* Comply with strange Sun cc calling convention for struct-returning
- functions. */
- if (!using_gcc
- && (TYPE_CODE (value_type) == TYPE_CODE_STRUCT
- || TYPE_CODE (value_type) == TYPE_CODE_UNION))
- store_unsigned_integer (dummy + CALL_DUMMY_CALL_OFFSET + 8, 4,
- TYPE_LENGTH (value_type) & 0x1fff);
+ /* If the called function returns an aggregate value, fill in the UNIMP
+ instruction containing the size of the returned aggregate return value,
+ which follows the call instruction.
+ For details see the SPARC Architecture Manual Version 8, Appendix D.3.
+
+ Adjust the call_dummy_breakpoint_offset for the bp_call_dummy breakpoint
+ to the proper address in the call dummy, so that `finish' after a stop
+ in a call dummy works.
+ Tweeking current_gdbarch is not an optimal solution, but the call to
+ sparc_fix_call_dummy is immediately followed by a call to run_stack_dummy,
+ which is the only function where dummy_breakpoint_offset is actually
+ used, if it is non-zero. */
+ if (TYPE_CODE (value_type) == TYPE_CODE_STRUCT
+ || TYPE_CODE (value_type) == TYPE_CODE_UNION)
+ {
+ store_unsigned_integer (dummy + CALL_DUMMY_CALL_OFFSET + 8, 4,
+ TYPE_LENGTH (value_type) & 0x1fff);
+ set_gdbarch_call_dummy_breakpoint_offset (current_gdbarch, 0x30);
+ }
+ else
+ set_gdbarch_call_dummy_breakpoint_offset (current_gdbarch, 0x2c);
if (!(GDB_TARGET_IS_SPARC64))
{
/* Set target byte order based on machine type. */
static int
-sparc_target_architecture_hook (ap)
- const bfd_arch_info_type *ap;
+sparc_target_architecture_hook (const bfd_arch_info_type *ap)
{
int i, j;
struct gdbarch_list *arches);
void
-_initialize_sparc_tdep ()
+_initialize_sparc_tdep (void)
{
/* Hook us into the gdbarch mechanism. */
register_gdbarch_init (bfd_arch_sparc, sparc_gdbarch_init);
}
void
-sparc64_write_sp (val)
- CORE_ADDR val;
+sparc64_write_sp (CORE_ADDR val)
{
CORE_ADDR oldsp = read_register (SP_REGNUM);
if (oldsp & 1)
}
void
-sparc64_write_fp (val)
- CORE_ADDR val;
+sparc64_write_fp (CORE_ADDR val)
{
CORE_ADDR oldfp = read_register (FP_REGNUM);
if (oldfp & 1)
int and float, we will waste every other register of both types. */
CORE_ADDR
-sparc64_push_arguments (nargs, args, sp, struct_return, struct_retaddr)
- int nargs;
- value_ptr *args;
- CORE_ADDR sp;
- int struct_return;
- CORE_ADDR struct_retaddr;
+sparc64_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
+ int struct_return, CORE_ADDR struct_retaddr)
{
int i, j, register_counter = 0;
CORE_ADDR tempsp;
for (i = nargs - 1; i >= 0; i--)
{
int len = TYPE_LENGTH (check_typedef (VALUE_TYPE (args[i])));
- value_ptr copyarg = args[i];
+ struct value *copyarg = args[i];
int copylen = len;
if (copylen < SPARC_INTREG_SIZE)
for (i = 0; i < nargs; i++)
{
int len = TYPE_LENGTH (check_typedef (VALUE_TYPE (args[i])));
- value_ptr copyarg = args[i];
+ struct value *copyarg = args[i];
enum type_code typecode = TYPE_CODE (VALUE_TYPE (args[i]));
int copylen = len;
fpreg = FP0_REGNUM + 2 * register_counter;
register_counter += 2;
break;
+ default:
+ internal_error (__FILE__, __LINE__, "bad switch");
}
write_register_bytes (REGISTER_BYTE (fpreg),
VALUE_CONTENTS (args[i]),
returned in f0-f3). */
void
-sp64_extract_return_value (type, regbuf, valbuf, bitoffset)
- struct type *type;
- char *regbuf;
- char *valbuf;
- int bitoffset;
+sp64_extract_return_value (struct type *type, char *regbuf, char *valbuf,
+ int bitoffset)
{
int typelen = TYPE_LENGTH (type);
int regsize = REGISTER_RAW_SIZE (O0_REGNUM);
{ /* no-op */
}
-/* The frame address: stored in the 'frame' field of the frame_info. */
-
-static CORE_ADDR
-sparc_frame_address (struct frame_info *fi)
-{
- return fi->frame;
-}
-
/* gdbarch fix call dummy:
All this function does is rearrange the arguments before calling
sparc_fix_call_dummy (which does the real work). */
return arches->gdbarch;
/* None found: is the request for a sparc architecture? */
- if (info.bfd_architecture != bfd_arch_sparc)
+ if (info.bfd_arch_info->arch != bfd_arch_sparc)
return NULL; /* No; then it's not for us. */
/* Yes: create a new gdbarch for the specified machine type. */
set_gdbarch_float_bit (gdbarch, 4 * TARGET_CHAR_BIT);
set_gdbarch_fp_regnum (gdbarch, SPARC_FP_REGNUM);
set_gdbarch_fp0_regnum (gdbarch, SPARC_FP0_REGNUM);
- set_gdbarch_frame_args_address (gdbarch, sparc_frame_address);
+ set_gdbarch_frame_args_address (gdbarch, default_frame_address);
set_gdbarch_frame_chain (gdbarch, sparc_frame_chain);
set_gdbarch_frame_init_saved_regs (gdbarch, sparc_frame_init_saved_regs);
- set_gdbarch_frame_locals_address (gdbarch, sparc_frame_address);
+ set_gdbarch_frame_locals_address (gdbarch, default_frame_address);
set_gdbarch_frame_num_args (gdbarch, frame_num_args_unknown);
set_gdbarch_frame_saved_pc (gdbarch, sparc_frame_saved_pc);
set_gdbarch_frameless_function_invocation (gdbarch,
set_gdbarch_long_long_bit (gdbarch, 8 * TARGET_CHAR_BIT);
set_gdbarch_max_register_raw_size (gdbarch, 8);
set_gdbarch_max_register_virtual_size (gdbarch, 8);
-#ifdef DO_CALL_DUMMY_ON_STACK
- set_gdbarch_pc_in_call_dummy (gdbarch, pc_in_call_dummy_on_stack);
-#else
- set_gdbarch_pc_in_call_dummy (gdbarch, pc_in_call_dummy_at_entry_point);
-#endif
set_gdbarch_pop_frame (gdbarch, sparc_pop_frame);
set_gdbarch_push_return_address (gdbarch, sparc_push_return_address);
set_gdbarch_push_dummy_frame (gdbarch, sparc_push_dummy_frame);
/* 32-bit machine types: */
#ifdef SPARC32_CALL_DUMMY_ON_STACK
+ set_gdbarch_pc_in_call_dummy (gdbarch, pc_in_call_dummy_on_stack);
set_gdbarch_call_dummy_address (gdbarch, sparc_call_dummy_address);
set_gdbarch_call_dummy_breakpoint_offset (gdbarch, 0x30);
set_gdbarch_call_dummy_length (gdbarch, 0x38);
set_gdbarch_call_dummy_location (gdbarch, ON_STACK);
set_gdbarch_call_dummy_words (gdbarch, call_dummy_32);
#else
+ set_gdbarch_pc_in_call_dummy (gdbarch, pc_in_call_dummy_at_entry_point);
set_gdbarch_call_dummy_address (gdbarch, entry_point_address);
set_gdbarch_call_dummy_breakpoint_offset (gdbarch, 0);
set_gdbarch_call_dummy_length (gdbarch, 0);
default: /* Any new machine type is likely to be 64-bit. */
#ifdef SPARC64_CALL_DUMMY_ON_STACK
+ set_gdbarch_pc_in_call_dummy (gdbarch, pc_in_call_dummy_on_stack);
set_gdbarch_call_dummy_address (gdbarch, sparc_call_dummy_address);
set_gdbarch_call_dummy_breakpoint_offset (gdbarch, 8 * 4);
set_gdbarch_call_dummy_length (gdbarch, 192);
set_gdbarch_call_dummy_start_offset (gdbarch, 148);
set_gdbarch_call_dummy_words (gdbarch, call_dummy_64);
#else
+ set_gdbarch_pc_in_call_dummy (gdbarch, pc_in_call_dummy_at_entry_point);
set_gdbarch_call_dummy_address (gdbarch, entry_point_address);
set_gdbarch_call_dummy_breakpoint_offset (gdbarch, 0);
set_gdbarch_call_dummy_length (gdbarch, 0);