/* 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, 2002 Free Software Foundation,
+ Inc.
This file is part of GDB.
#include "arch-utils.h"
#include "frame.h"
#include "inferior.h"
-#include "obstack.h"
#include "target.h"
#include "value.h"
#include "bfd.h"
#include "gdb_string.h"
+#include "regcache.h"
+#include "osabi.h"
#ifdef USE_PROC_FS
#include <sys/procfs.h>
+/* Prototypes for supply_gregset etc. */
+#include "gregset.h"
#endif
#include "gdbcore.h"
#include "symfile.h" /* for 'entry_point_address' */
-/* Prototypes for supply_gregset etc. */
-#include "gregset.h"
-
/*
* Some local macros that have multi-arch and non-multi-arch versions:
*/
int reg_save_offset;
int call_dummy_call_offset;
int print_insn_mach;
+
+ enum gdb_osabi osabi;
};
/* Now make GDB_TARGET_IS_SPARC64 a runtime test. */
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;
/* Compute ->frame as if not flat. If it is flat, we'll change
it later. */
if (fi->next->next != NULL
- && (fi->next->next->signal_handler_caller
- || frame_in_dummy (fi->next->next))
+ && ((get_frame_type (fi->next->next) == SIGTRAMP_FRAME)
+ || deprecated_frame_in_dummy (fi->next->next))
&& frameless_look_for_prologue (fi->next))
{
/* A frameless function interrupted by a signal did not change
the frame pointer, fix up frame pointer accordingly. */
- fi->frame = FRAME_FP (fi->next);
+ deprecated_update_frame_base_hack (fi, get_frame_base (fi->next));
fi->extra_info->bottom = fi->next->extra_info->bottom;
}
else
{
/* Should we adjust for stack bias here? */
get_saved_register (buf, 0, 0, fi, FP_REGNUM, 0);
- fi->frame = extract_address (buf, REGISTER_RAW_SIZE (FP_REGNUM));
+ deprecated_update_frame_base_hack (fi, extract_address (buf, REGISTER_RAW_SIZE (FP_REGNUM)));
if (GDB_TARGET_IS_SPARC64 && (fi->frame & 1))
- fi->frame += 2047;
+ deprecated_update_frame_base_hack (fi, fi->frame + 2047);
}
}
frame. For such functions, the frame pointer is actually in %i7. */
fi->extra_info->flat = 0;
fi->extra_info->in_prologue = 0;
- if (find_pc_partial_function (fi->pc, &name, &prologue_start, &prologue_end))
+ if (find_pc_partial_function (get_frame_pc (fi), &name, &prologue_start, &prologue_end))
{
/* See if the function starts with an add (which will be of a
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)
{
/* Overwrite the frame's address with the value in %i7. */
get_saved_register (buf, 0, 0, fi, I7_REGNUM, 0);
- fi->frame = extract_address (buf, REGISTER_RAW_SIZE (I7_REGNUM));
+ deprecated_update_frame_base_hack (fi, extract_address (buf, REGISTER_RAW_SIZE (I7_REGNUM)));
if (GDB_TARGET_IS_SPARC64 && (fi->frame & 1))
- fi->frame += 2047;
+ deprecated_update_frame_base_hack (fi, fi->frame + 2047);
/* Record where the fp got saved. */
fi->extra_info->fp_addr =
sal = find_pc_line (prologue_start, 0);
if (sal.line == 0) /* no line info, use PC */
- prologue_end = fi->pc;
+ prologue_end = get_frame_pc (fi);
else if (sal.end < prologue_end)
prologue_end = sal.end;
- if (fi->pc < prologue_end)
+ if (get_frame_pc (fi) < prologue_end)
{
- for (addr = prologue_start; addr < fi->pc; addr += 4)
+ for (addr = prologue_start; addr < get_frame_pc (fi); addr += 4)
{
insn = read_memory_integer (addr, 4);
if (X_OP (insn) == 2 && X_OP3 (insn) == 0x3c)
break; /* SAVE seen, stop searching */
}
- if (addr >= fi->pc)
+ if (addr >= get_frame_pc (fi))
{
fi->extra_info->in_prologue = 1;
- fi->frame = read_register (SP_REGNUM);
+ deprecated_update_frame_base_hack (fi, read_register (SP_REGNUM));
}
}
}
if (fi->next && fi->frame == 0)
{
/* Kludge to cause init_prev_frame_info to destroy the new frame. */
- fi->frame = fi->next->frame;
- fi->pc = fi->next->pc;
+ deprecated_update_frame_base_hack (fi, fi->next->frame);
+ deprecated_update_frame_pc_hack (fi, get_frame_pc (fi->next));
}
}
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;
buf = alloca (MAX_REGISTER_RAW_SIZE);
- if (frame->signal_handler_caller)
+ if ((get_frame_type (frame) == SIGTRAMP_FRAME))
{
/* This is the signal trampoline frame.
Get the saved PC from the sigcontext structure. */
/* Solaris2 ucbsigvechandler passes a pointer to a sigcontext
as the third parameter. The offset to the saved pc is 12. */
- find_pc_partial_function (frame->pc, &name,
+ find_pc_partial_function (get_frame_pc (frame), &name,
(CORE_ADDR *) NULL, (CORE_ADDR *) NULL);
if (name && STREQ (name, "ucbsigvechandler"))
saved_pc_offset = 12;
}
else if (frame->extra_info->in_prologue ||
(frame->next != NULL &&
- (frame->next->signal_handler_caller ||
- frame_in_dummy (frame->next)) &&
+ ((get_frame_type (frame->next) == SIGTRAMP_FRAME) ||
+ deprecated_frame_in_dummy (frame->next)) &&
frameless_look_for_prologue (frame)))
{
/* A frameless function interrupted by a signal did not save
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);
+ deprecated_update_frame_pc_hack (frame, FRAME_SAVED_PC (frame));
return 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;
return pc;
}
+/* Advance PC across any function entry prologue instructions to reach
+ some "real" code. */
+
CORE_ADDR
-sparc_skip_prologue (start_pc, frameless_p)
- CORE_ADDR start_pc;
- int frameless_p;
+sparc_skip_prologue (CORE_ADDR start_pc)
+{
+ struct symtab_and_line sal;
+ CORE_ADDR func_start, func_end;
+
+ /* This is the preferred method, find the end of the prologue by
+ using the debugging information. */
+ if (find_pc_partial_function (start_pc, NULL, &func_start, &func_end))
+ {
+ sal = find_pc_line (func_start, 0);
+
+ if (sal.end < func_end
+ && start_pc <= sal.end)
+ return sal.end;
+ }
+
+ /* Oh well, examine the code by hand. */
+ return examine_prologue (start_pc, 0, NULL, NULL);
+}
+
+/* Is the prologue at IP frameless? */
+
+int
+sparc_prologue_frameless_p (CORE_ADDR ip)
{
- return examine_prologue (start_pc, frameless_p, NULL, NULL);
+ return ip == examine_prologue (ip, 1, NULL, NULL);
}
/* Check instruction at ADDR to see if it is a branch.
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;
/* error ("No selected frame."); */
if (!target_has_registers)
error ("The program has no registers now.");
- if (selected_frame == NULL)
+ if (deprecated_selected_frame == NULL)
error ("No selected frame.");
/* Try to use selected frame */
- frame = get_prev_frame (selected_frame);
+ frame = get_prev_frame (deprecated_selected_frame);
if (frame == 0)
error ("Cmd not meaningful in the outermost frame.");
}
if (raw_buffer != NULL)
{
/* Put it back in target format. */
- store_address (raw_buffer, REGISTER_RAW_SIZE (regnum), frame->pc);
+ store_address (raw_buffer, REGISTER_RAW_SIZE (regnum), get_frame_pc (frame));
}
if (addrp != NULL)
*addrp = 0;
{
/* FIXME MVS: wrong test for dummy frame at entry. */
- if (frame1->pc >= (frame1->extra_info->bottom ?
+ if (get_frame_pc (frame1) >= (frame1->extra_info->bottom ?
frame1->extra_info->bottom : read_sp ())
- && frame1->pc <= FRAME_FP (frame1))
+ && get_frame_pc (frame1) <= get_frame_base (frame1))
{
/* Dummy frame. All but the window regs are in there somewhere.
The window registers are saved on the stack, just like in a
addr = frame1->frame + (regnum - G0_REGNUM) * SPARC_INTREG_SIZE
- (FP_REGISTER_BYTES + 8 * SPARC_INTREG_SIZE);
else if (regnum >= I0_REGNUM && regnum < I0_REGNUM + 8)
- addr = (frame1->prev->extra_info->bottom
+ /* NOTE: cagney/2002-05-04: The call to get_prev_frame()
+ is safe/cheap - there will always be a prev frame.
+ This is because frame1 is initialized to frame->next
+ (frame1->prev == frame) and is then advanced towards
+ the innermost (next) frame. */
+ addr = (get_prev_frame (frame1)->extra_info->bottom
+ (regnum - I0_REGNUM) * SPARC_INTREG_SIZE
+ FRAME_SAVED_I0);
else if (regnum >= L0_REGNUM && regnum < L0_REGNUM + 8)
- addr = (frame1->prev->extra_info->bottom
+ /* NOTE: cagney/2002-05-04: The call to get_prev_frame()
+ is safe/cheap - there will always be a prev frame.
+ This is because frame1 is initialized to frame->next
+ (frame1->prev == frame) and is then advanced towards
+ the innermost (next) frame. */
+ addr = (get_prev_frame (frame1)->extra_info->bottom
+ (regnum - L0_REGNUM) * SPARC_INTREG_SIZE
+ FRAME_SAVED_L0);
else if (regnum >= O0_REGNUM && regnum < O0_REGNUM + 8)
regs = alloca (NUM_REGS * sizeof (CORE_ADDR));
memset (regs, 0, NUM_REGS * sizeof (CORE_ADDR));
- find_pc_partial_function (frame1->pc, NULL, &func_start, NULL);
+ find_pc_partial_function (get_frame_pc (frame1), NULL, &func_start, NULL);
examine_prologue (func_start, 0, frame1, regs);
addr = regs[regnum];
}
{
/* Normal frame. Local and In registers are saved on stack. */
if (regnum >= I0_REGNUM && regnum < I0_REGNUM + 8)
- addr = (frame1->prev->extra_info->bottom
+ addr = (get_prev_frame (frame1)->extra_info->bottom
+ (regnum - I0_REGNUM) * SPARC_INTREG_SIZE
+ FRAME_SAVED_I0);
else if (regnum >= L0_REGNUM && regnum < L0_REGNUM + 8)
- addr = (frame1->prev->extra_info->bottom
+ addr = (get_prev_frame (frame1)->extra_info->bottom
+ (regnum - L0_REGNUM) * SPARC_INTREG_SIZE
+ FRAME_SAVED_L0);
else if (regnum >= O0_REGNUM && regnum < O0_REGNUM + 8)
*lval = lval_register;
addr = REGISTER_BYTE (regnum);
if (raw_buffer != NULL)
- read_register_gen (regnum, raw_buffer);
+ deprecated_read_register_gen (regnum, raw_buffer);
}
if (addrp != NULL)
*addrp = 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;
if (GDB_TARGET_IS_SPARC64)
{
/* PC, NPC, CCR, FSR, FPRS, Y, ASI */
- read_register_bytes (REGISTER_BYTE (PC_REGNUM), ®ister_temp[0],
- REGISTER_RAW_SIZE (PC_REGNUM) * 7);
- read_register_bytes (REGISTER_BYTE (PSTATE_REGNUM),
- ®ister_temp[7 * SPARC_INTREG_SIZE],
- REGISTER_RAW_SIZE (PSTATE_REGNUM));
+ deprecated_read_register_bytes (REGISTER_BYTE (PC_REGNUM),
+ ®ister_temp[0],
+ REGISTER_RAW_SIZE (PC_REGNUM) * 7);
+ deprecated_read_register_bytes (REGISTER_BYTE (PSTATE_REGNUM),
+ ®ister_temp[7 * SPARC_INTREG_SIZE],
+ REGISTER_RAW_SIZE (PSTATE_REGNUM));
/* FIXME: not sure what needs to be saved here. */
}
else
{
/* Y, PS, WIM, TBR, PC, NPC, FPS, CPS regs */
- read_register_bytes (REGISTER_BYTE (Y_REGNUM), ®ister_temp[0],
- REGISTER_RAW_SIZE (Y_REGNUM) * 8);
+ deprecated_read_register_bytes (REGISTER_BYTE (Y_REGNUM),
+ ®ister_temp[0],
+ REGISTER_RAW_SIZE (Y_REGNUM) * 8);
}
- read_register_bytes (REGISTER_BYTE (O0_REGNUM),
- ®ister_temp[8 * SPARC_INTREG_SIZE],
- SPARC_INTREG_SIZE * 8);
+ deprecated_read_register_bytes (REGISTER_BYTE (O0_REGNUM),
+ ®ister_temp[8 * SPARC_INTREG_SIZE],
+ SPARC_INTREG_SIZE * 8);
- read_register_bytes (REGISTER_BYTE (G0_REGNUM),
- ®ister_temp[16 * SPARC_INTREG_SIZE],
- SPARC_INTREG_SIZE * 8);
+ deprecated_read_register_bytes (REGISTER_BYTE (G0_REGNUM),
+ ®ister_temp[16 * SPARC_INTREG_SIZE],
+ SPARC_INTREG_SIZE * 8);
if (SPARC_HAS_FPU)
- read_register_bytes (REGISTER_BYTE (FP0_REGNUM),
- ®ister_temp[24 * SPARC_INTREG_SIZE],
- FP_REGISTER_BYTES);
+ deprecated_read_register_bytes (REGISTER_BYTE (FP0_REGNUM),
+ ®ister_temp[24 * SPARC_INTREG_SIZE],
+ FP_REGISTER_BYTES);
sp -= DUMMY_STACK_SIZE;
if (strcmp (target_shortname, "sim") != 0)
{
- write_fp (old_sp);
-
+ /* NOTE: cagney/2002-04-04: The code below originally contained
+ GDB's _only_ call to write_fp(). That call was eliminated by
+ inlining the corresponding code. For the 64 bit case, the
+ old function (sparc64_write_fp) did the below although I'm
+ not clear why. The same goes for why this is only done when
+ the underlying target is a simulator. */
+ if (GDB_TARGET_IS_SPARC64)
+ {
+ /* Target is a 64 bit SPARC. */
+ CORE_ADDR oldfp = read_register (FP_REGNUM);
+ if (oldfp & 1)
+ write_register (FP_REGNUM, old_sp - 2047);
+ else
+ write_register (FP_REGNUM, old_sp);
+ }
+ else
+ {
+ /* Target is a 32 bit SPARC. */
+ write_register (FP_REGNUM, old_sp);
+ }
/* Set return address register for the call dummy to the current PC. */
write_register (I7_REGNUM, read_pc () - 8);
}
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);
+ CORE_ADDR frame_addr = get_frame_base (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));
- if (fi->pc >= (fi->extra_info->bottom ?
+ if (get_frame_pc (fi) >= (fi->extra_info->bottom ?
fi->extra_info->bottom : read_sp ())
- && fi->pc <= FRAME_FP (fi))
+ && get_frame_pc (fi) <= get_frame_base (fi))
{
/* Dummy frame. All but the window regs are in there somewhere. */
for (regnum = G1_REGNUM; regnum < G1_REGNUM + 7; regnum++)
else if (fi->extra_info->flat)
{
CORE_ADDR func_start;
- find_pc_partial_function (fi->pc, NULL, &func_start, NULL);
+ find_pc_partial_function (get_frame_pc (fi), NULL, &func_start, NULL);
examine_prologue (func_start, 0, fi, saved_regs_addr);
/* Flat register window frame. */
}
/* Otherwise, whatever we would get from ptrace(GETREGS) is accurate */
/* FIXME -- should this adjust for the sparc64 offset? */
- saved_regs_addr[SP_REGNUM] = FRAME_FP (fi);
+ saved_regs_addr[SP_REGNUM] = get_frame_base (fi);
}
/* Discard from the stack the innermost frame, restoring all saved registers.
- Note that the values stored in fsr by get_frame_saved_regs are *in
- the context of the called frame*. What this means is that the i
- regs of fsr must be restored into the o regs of the (calling) frame that
- we pop into. We don't care about the output regs of the calling frame,
- since unless it's a dummy frame, it won't have any output regs in it.
+ Note that the values stored in fsr by
+ deprecated_get_frame_saved_regs are *in the context of the called
+ frame*. What this means is that the i regs of fsr must be restored
+ into the o regs of the (calling) frame that we pop into. We don't
+ care about the output regs of the calling frame, since unless it's
+ a dummy frame, it won't have any output regs in it.
We never have to bother with %l (local) regs, since the called routine's
locals get tossed, and the calling routine's locals are already saved
/* 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;
if (fsr[FP0_REGNUM])
{
read_memory (fsr[FP0_REGNUM], raw_buffer, FP_REGISTER_BYTES);
- write_register_bytes (REGISTER_BYTE (FP0_REGNUM),
- raw_buffer, FP_REGISTER_BYTES);
+ deprecated_write_register_bytes (REGISTER_BYTE (FP0_REGNUM),
+ raw_buffer, FP_REGISTER_BYTES);
}
if (!(GDB_TARGET_IS_SPARC64))
{
if (fsr[FPS_REGNUM])
{
read_memory (fsr[FPS_REGNUM], raw_buffer, SPARC_INTREG_SIZE);
- write_register_gen (FPS_REGNUM, raw_buffer);
+ deprecated_write_register_gen (FPS_REGNUM, raw_buffer);
}
if (fsr[CPS_REGNUM])
{
read_memory (fsr[CPS_REGNUM], raw_buffer, SPARC_INTREG_SIZE);
- write_register_gen (CPS_REGNUM, raw_buffer);
+ deprecated_write_register_gen (CPS_REGNUM, raw_buffer);
}
}
}
if (fsr[G1_REGNUM])
{
read_memory (fsr[G1_REGNUM], raw_buffer, 7 * SPARC_INTREG_SIZE);
- write_register_bytes (REGISTER_BYTE (G1_REGNUM), raw_buffer,
- 7 * SPARC_INTREG_SIZE);
+ deprecated_write_register_bytes (REGISTER_BYTE (G1_REGNUM), raw_buffer,
+ 7 * SPARC_INTREG_SIZE);
}
if (frame->extra_info->flat)
char *reg_temp;
- reg_temp = alloca (REGISTER_BYTES);
+ reg_temp = alloca (SPARC_INTREG_SIZE * 16);
read_memory (fsr[I0_REGNUM], raw_buffer, 8 * SPARC_INTREG_SIZE);
/* Restore the out registers.
Among other things this writes the new stack pointer. */
- write_register_bytes (REGISTER_BYTE (O0_REGNUM), raw_buffer,
- SPARC_INTREG_SIZE * 8);
+ deprecated_write_register_bytes (REGISTER_BYTE (O0_REGNUM), raw_buffer,
+ SPARC_INTREG_SIZE * 8);
- write_register_bytes (REGISTER_BYTE (L0_REGNUM), reg_temp,
- SPARC_INTREG_SIZE * 16);
+ deprecated_write_register_bytes (REGISTER_BYTE (L0_REGNUM), reg_temp,
+ SPARC_INTREG_SIZE * 16);
}
if (!(GDB_TARGET_IS_SPARC64))
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];
register values. */
void
-supply_gregset (gregsetp)
- gdb_gregset_t *gregsetp;
+supply_gregset (gdb_gregset_t *gregsetp)
{
prgreg_t *regp = (prgreg_t *) gregsetp;
int regi, offset = 0;
}
void
-fill_gregset (gregsetp, regno)
- gdb_gregset_t *gregsetp;
- int regno;
+fill_gregset (gdb_gregset_t *gregsetp, int regno)
{
prgreg_t *regp = (prgreg_t *) gregsetp;
int regi, offset = 0;
for (regi = 0; regi <= R_I7; regi++)
if ((regno == -1) || (regno == regi))
- read_register_gen (regi, (char *) (regp + regi) + offset);
+ deprecated_read_register_gen (regi, (char *) (regp + regi) + offset);
if ((regno == -1) || (regno == PC_REGNUM))
- read_register_gen (PC_REGNUM, (char *) (regp + R_PC) + offset);
+ deprecated_read_register_gen (PC_REGNUM, (char *) (regp + R_PC) + offset);
if ((regno == -1) || (regno == NPC_REGNUM))
- read_register_gen (NPC_REGNUM, (char *) (regp + R_nPC) + offset);
+ deprecated_read_register_gen (NPC_REGNUM, (char *) (regp + R_nPC) + offset);
if ((regno == -1) || (regno == Y_REGNUM))
- read_register_gen (Y_REGNUM, (char *) (regp + R_Y) + offset);
+ deprecated_read_register_gen (Y_REGNUM, (char *) (regp + R_Y) + offset);
if (GDB_TARGET_IS_SPARC64)
{
#ifdef R_CCR
if (regno == -1 || regno == CCR_REGNUM)
- read_register_gen (CCR_REGNUM, ((char *) (regp + R_CCR)) + offset);
+ deprecated_read_register_gen (CCR_REGNUM, ((char *) (regp + R_CCR)) + offset);
#endif
#ifdef R_FPRS
if (regno == -1 || regno == FPRS_REGNUM)
- read_register_gen (FPRS_REGNUM, ((char *) (regp + R_FPRS)) + offset);
+ deprecated_read_register_gen (FPRS_REGNUM, ((char *) (regp + R_FPRS)) + offset);
#endif
#ifdef R_ASI
if (regno == -1 || regno == ASI_REGNUM)
- read_register_gen (ASI_REGNUM, ((char *) (regp + R_ASI)) + offset);
+ deprecated_read_register_gen (ASI_REGNUM, ((char *) (regp + R_ASI)) + offset);
#endif
}
else /* sparc32 */
{
#ifdef R_PS
if (regno == -1 || regno == PS_REGNUM)
- read_register_gen (PS_REGNUM, ((char *) (regp + R_PS)) + offset);
+ deprecated_read_register_gen (PS_REGNUM, ((char *) (regp + R_PS)) + offset);
#endif
/* For 64-bit hosts, R_WIM and R_TBR may not be defined.
#if defined (R_WIM)
if (regno == -1 || regno == WIM_REGNUM)
- read_register_gen (WIM_REGNUM, ((char *) (regp + R_WIM)) + offset);
+ deprecated_read_register_gen (WIM_REGNUM, ((char *) (regp + R_WIM)) + offset);
#else
if (regno == -1 || regno == WIM_REGNUM)
- read_register_gen (WIM_REGNUM, NULL);
+ deprecated_read_register_gen (WIM_REGNUM, NULL);
#endif
#if defined (R_TBR)
if (regno == -1 || regno == TBR_REGNUM)
- read_register_gen (TBR_REGNUM, ((char *) (regp + R_TBR)) + offset);
+ deprecated_read_register_gen (TBR_REGNUM, ((char *) (regp + R_TBR)) + offset);
#else
if (regno == -1 || regno == TBR_REGNUM)
- read_register_gen (TBR_REGNUM, NULL);
+ deprecated_read_register_gen (TBR_REGNUM, NULL);
#endif
}
}
idea of the current floating point register values. */
void
-supply_fpregset (fpregsetp)
- gdb_fpregset_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)
- gdb_fpregset_t *fpregsetp;
- int regno;
+fill_fpregset (gdb_fpregset_t *fpregsetp, int regno)
{
int regi;
char *to;
{
if ((regno == -1) || (regno == regi))
{
- from = (char *) ®isters[REGISTER_BYTE (regi)];
+ from = (char *) &deprecated_registers[REGISTER_BYTE (regi)];
to = (char *) &fpregsetp->pr_fr.pr_regs[regi - FP0_REGNUM];
memcpy (to, from, REGISTER_RAW_SIZE (regi));
}
if (!(GDB_TARGET_IS_SPARC64)) /* FIXME: does Sparc64 have this register? */
if ((regno == -1) || (regno == FPS_REGNUM))
{
- from = (char *)®isters[REGISTER_BYTE (FPS_REGNUM)];
+ from = (char *)&deprecated_registers[REGISTER_BYTE (FPS_REGNUM)];
to = (char *) &fpregsetp->pr_fsr;
memcpy (to, from, REGISTER_RAW_SIZE (FPS_REGNUM));
}
#endif /* USE_PROC_FS */
-
-#ifdef GET_LONGJMP_TARGET
+/* Because of Multi-arch, GET_LONGJMP_TARGET is always defined. So test
+ for a definition of JB_PC. */
+#ifdef JB_PC
/* 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
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)
Pretty print various registers. */
/* FIXME: Would be nice if this did some fancy things for 32 bit sparc. */
-void
-sparc_print_register_hook (regno)
- int regno;
+static void
+sparc_print_register_hook (int regno)
{
ULONGEST val;
{
char value[16];
- if (!read_relative_register_raw_bytes (regno, value)
- && !read_relative_register_raw_bytes (regno + 1, value + 4))
+ if (frame_register_read (deprecated_selected_frame, regno, value)
+ && frame_register_read (deprecated_selected_frame, regno + 1, value + 4))
{
printf_unfiltered ("\t");
print_floating (value, builtin_type_double, gdb_stdout);
#if 0 /* FIXME: gdb doesn't handle long doubles */
if ((regno & 3) == 0)
{
- if (!read_relative_register_raw_bytes (regno + 2, value + 8)
- && !read_relative_register_raw_bytes (regno + 3, value + 12))
+ if (frame_register_read (deprecated_selected_frame, regno + 2, value + 8)
+ && frame_register_read (deprecated_selected_frame, regno + 3, value + 12))
{
printf_unfiltered ("\t");
print_floating (value, builtin_type_long_double, gdb_stdout);
{
char value[16];
- if (!read_relative_register_raw_bytes (regno, value)
- && !read_relative_register_raw_bytes (regno + 1, value + 8))
+ if (frame_register_read (deprecated_selected_frame, regno, value)
+ && frame_register_read (deprecated_selected_frame, regno + 1, value + 8))
{
printf_unfiltered ("\t");
print_floating (value, builtin_type_long_double, gdb_stdout);
#undef BITS
}
+
+static void
+sparc_print_registers (struct gdbarch *gdbarch,
+ struct ui_file *file,
+ struct frame_info *frame,
+ int regnum, int print_all,
+ void (*print_register_hook) (int))
+{
+ int i;
+ const int numregs = NUM_REGS + NUM_PSEUDO_REGS;
+ char *raw_buffer = alloca (MAX_REGISTER_RAW_SIZE);
+ char *virtual_buffer = alloca (MAX_REGISTER_VIRTUAL_SIZE);
+
+ for (i = 0; i < numregs; i++)
+ {
+ /* Decide between printing all regs, non-float / vector regs, or
+ specific reg. */
+ if (regnum == -1)
+ {
+ if (!print_all)
+ {
+ if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (i)) == TYPE_CODE_FLT)
+ continue;
+ if (TYPE_VECTOR (REGISTER_VIRTUAL_TYPE (i)))
+ continue;
+ }
+ }
+ else
+ {
+ if (i != regnum)
+ continue;
+ }
+
+ /* If the register name is empty, it is undefined for this
+ processor, so don't display anything. */
+ if (REGISTER_NAME (i) == NULL || *(REGISTER_NAME (i)) == '\0')
+ continue;
+
+ fputs_filtered (REGISTER_NAME (i), file);
+ print_spaces_filtered (15 - strlen (REGISTER_NAME (i)), file);
+
+ /* Get the data in raw format. */
+ if (! frame_register_read (frame, i, raw_buffer))
+ {
+ fprintf_filtered (file, "*value not available*\n");
+ continue;
+ }
+
+ /* FIXME: cagney/2002-08-03: This code shouldn't be necessary.
+ The function frame_register_read() should have returned the
+ pre-cooked register so no conversion is necessary. */
+ /* Convert raw data to virtual format if necessary. */
+ if (REGISTER_CONVERTIBLE (i))
+ {
+ REGISTER_CONVERT_TO_VIRTUAL (i, REGISTER_VIRTUAL_TYPE (i),
+ raw_buffer, virtual_buffer);
+ }
+ else
+ {
+ memcpy (virtual_buffer, raw_buffer,
+ REGISTER_VIRTUAL_SIZE (i));
+ }
+
+ /* If virtual format is floating, print it that way, and in raw
+ hex. */
+ if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (i)) == TYPE_CODE_FLT)
+ {
+ int j;
+
+ val_print (REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0, 0,
+ file, 0, 1, 0, Val_pretty_default);
+
+ fprintf_filtered (file, "\t(raw 0x");
+ for (j = 0; j < REGISTER_RAW_SIZE (i); j++)
+ {
+ int idx;
+ if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
+ idx = j;
+ else
+ idx = REGISTER_RAW_SIZE (i) - 1 - j;
+ fprintf_filtered (file, "%02x", (unsigned char) raw_buffer[idx]);
+ }
+ fprintf_filtered (file, ")");
+ }
+ else
+ {
+ /* Print the register in hex. */
+ val_print (REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0, 0,
+ file, 'x', 1, 0, Val_pretty_default);
+ /* If not a vector register, print it also according to its
+ natural format. */
+ if (TYPE_VECTOR (REGISTER_VIRTUAL_TYPE (i)) == 0)
+ {
+ fprintf_filtered (file, "\t");
+ val_print (REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0, 0,
+ file, 0, 1, 0, Val_pretty_default);
+ }
+ }
+
+ /* Some sparc specific info. */
+ if (print_register_hook != NULL)
+ print_register_hook (i);
+
+ fprintf_filtered (file, "\n");
+ }
+}
+
+static void
+sparc_print_registers_info (struct gdbarch *gdbarch,
+ struct ui_file *file,
+ struct frame_info *frame,
+ int regnum, int print_all)
+{
+ sparc_print_registers (gdbarch, file, frame, regnum, print_all,
+ sparc_print_register_hook);
+}
+
+void
+sparc_do_registers_info (int regnum, int all)
+{
+ sparc_print_registers_info (current_gdbarch, gdb_stdout, deprecated_selected_frame,
+ regnum, all);
+}
+
+static void
+sparclet_print_registers_info (struct gdbarch *gdbarch,
+ struct ui_file *file,
+ struct frame_info *frame,
+ int regnum, int print_all)
+{
+ sparc_print_registers (gdbarch, file, frame, regnum, print_all, NULL);
+}
+
+void
+sparclet_do_registers_info (int regnum, int all)
+{
+ sparclet_print_registers_info (current_gdbarch, gdb_stdout,
+ deprecated_selected_frame, regnum, all);
+}
+
\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))
for (j = 0;
j < m_arg->len && oregnum < 6;
j += SPARC_INTREG_SIZE, oregnum++)
- write_register_gen (O0_REGNUM + oregnum, m_arg->contents + j);
+ deprecated_write_register_gen (O0_REGNUM + oregnum, m_arg->contents + j);
}
return sp;
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);
memcpy (valbuf,
®buf[O0_REGNUM * regsize +
(typelen >= regsize
- || TARGET_BYTE_ORDER == LITTLE_ENDIAN ? 0
+ || TARGET_BYTE_ORDER == BFD_ENDIAN_LITTLE ? 0
: regsize - typelen)],
typelen);
}
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;
- buffer = alloca(MAX_REGISTER_RAW_SIZE);
+ buffer = alloca (MAX_REGISTER_RAW_SIZE);
if (TYPE_CODE (type) == TYPE_CODE_FLT && SPARC_HAS_FPU)
/* Floating-point values are returned in the register pair */
memset (buffer, 0, REGISTER_RAW_SIZE (regno));
memcpy (buffer + REGISTER_RAW_SIZE (regno) - TYPE_LENGTH (type), valbuf,
TYPE_LENGTH (type));
- write_register_gen (regno, buffer);
+ deprecated_write_register_gen (regno, buffer);
}
else
- write_register_bytes (REGISTER_BYTE (regno), valbuf, TYPE_LENGTH (type));
+ deprecated_write_register_bytes (REGISTER_BYTE (regno), valbuf,
+ TYPE_LENGTH (type));
}
extern void
sparclet_store_return_value (struct type *type, char *valbuf)
{
/* Other values are returned in register %o0. */
- write_register_bytes (REGISTER_BYTE (O0_REGNUM), valbuf,
- TYPE_LENGTH (type));
+ deprecated_write_register_bytes (REGISTER_BYTE (O0_REGNUM), valbuf,
+ TYPE_LENGTH (type));
}
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;
if (ap->mach == bfd_mach_sparc_sparclite_le)
{
- if (TARGET_BYTE_ORDER_SELECTABLE_P)
- {
- target_byte_order = LITTLE_ENDIAN;
- bi_endian = 1;
- }
- else
- {
- warning ("This GDB does not support little endian sparclite.");
- }
+ target_byte_order = BFD_ENDIAN_LITTLE;
+ bi_endian = 1;
}
else
bi_endian = 0;
static struct gdbarch * sparc_gdbarch_init (struct gdbarch_info info,
struct gdbarch_list *arches);
+static void sparc_dump_tdep (struct gdbarch *, struct ui_file *);
void
-_initialize_sparc_tdep ()
+_initialize_sparc_tdep (void)
{
/* Hook us into the gdbarch mechanism. */
- register_gdbarch_init (bfd_arch_sparc, sparc_gdbarch_init);
+ gdbarch_register (bfd_arch_sparc, sparc_gdbarch_init, sparc_dump_tdep);
tm_print_insn = gdb_print_insn_sparc;
tm_print_insn_info.mach = TM_PRINT_INSN_MACH; /* Selects sparc/sparclite */
}
void
-sparc64_write_sp (val)
- CORE_ADDR val;
+sparc64_write_sp (CORE_ADDR val)
{
CORE_ADDR oldsp = read_register (SP_REGNUM);
if (oldsp & 1)
write_register (SP_REGNUM, val);
}
-void
-sparc64_write_fp (val)
- CORE_ADDR val;
-{
- CORE_ADDR oldfp = read_register (FP_REGNUM);
- if (oldfp & 1)
- write_register (FP_REGNUM, val - 2047);
- else
- write_register (FP_REGNUM, val);
-}
-
/* The SPARC 64 ABI passes floating-point arguments in FP0 to FP31,
and all other arguments in O0 to O5. They are also copied onto
the stack in the correct places. Apparently (empirically),
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]),
- len);
+ deprecated_write_register_bytes (REGISTER_BYTE (fpreg),
+ VALUE_CONTENTS (args[i]),
+ len);
}
}
else /* all other args go into the first six 'o' registers */
{
int oreg = O0_REGNUM + register_counter;
- write_register_gen (oreg, VALUE_CONTENTS (copyarg) + j);
+ deprecated_write_register_gen (oreg, VALUE_CONTENTS (copyarg) + j);
register_counter += 1;
}
}
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);
/* MULTI_ARCH support */
-static char *
+static const char *
sparc32_register_name (int regno)
{
static char *register_names[] =
return register_names[regno];
}
-static char *
+static const char *
sparc64_register_name (int regno)
{
static char *register_names[] =
return register_names[regno];
}
-static char *
+static const char *
sparclite_register_name (int regno)
{
static char *register_names[] =
return register_names[regno];
}
-static char *
+static const char *
sparclet_register_name (int regno)
{
static char *register_names[] =
return 64 * 8 + (regno - 80) * 8;
}
-/* Advance PC across any function entry prologue instructions to reach
- some "real" code. SKIP_PROLOGUE_FRAMELESS_P advances the PC past
- some of the prologue, but stops as soon as it knows that the
- function has a frame. Its result is equal to its input PC if the
- function is frameless, unequal otherwise. */
-
-static CORE_ADDR
-sparc_gdbarch_skip_prologue (CORE_ADDR ip)
-{
- return examine_prologue (ip, 0, NULL, NULL);
-}
-
/* Immediately after a function call, return the saved pc.
Can't go through the frames for this because on some machines
the new frame is not set up until the new function executes
{ /* 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). */
{
struct gdbarch *gdbarch;
struct gdbarch_tdep *tdep;
+ enum gdb_osabi osabi = GDB_OSABI_UNKNOWN;
static LONGEST call_dummy_32[] =
{ 0xbc100001, 0x9de38000, 0xbc100002, 0xbe100003,
};
static LONGEST call_dummy_nil[] = {0};
+ /* Try to determine the OS ABI of the object we are loading. */
+
+ if (info.abfd != NULL)
+ {
+ osabi = gdbarch_lookup_osabi (info.abfd);
+ if (osabi == GDB_OSABI_UNKNOWN)
+ {
+ /* If it's an ELF file, assume it's Solaris. */
+ if (bfd_get_flavour (info.abfd) == bfd_target_elf_flavour)
+ osabi = GDB_OSABI_SOLARIS;
+ }
+ }
+
/* First see if there is already a gdbarch that can satisfy the request. */
- arches = gdbarch_list_lookup_by_info (arches, &info);
- if (arches != NULL)
- return arches->gdbarch;
+ for (arches = gdbarch_list_lookup_by_info (arches, &info);
+ arches != NULL;
+ arches = gdbarch_list_lookup_by_info (arches->next, &info))
+ {
+ /* Make sure the ABI selection matches. */
+ tdep = gdbarch_tdep (arches->gdbarch);
+ if (tdep && tdep->osabi == osabi)
+ 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. */
tdep = (struct gdbarch_tdep *) xmalloc (sizeof (struct gdbarch_tdep));
gdbarch = gdbarch_alloc (&info, tdep);
+ tdep->osabi = osabi;
+
/* First set settings that are common for all sparc architectures. */
set_gdbarch_believe_pcc_promotion (gdbarch, 1);
set_gdbarch_breakpoint_from_pc (gdbarch, memory_breakpoint_from_pc);
set_gdbarch_call_dummy_stack_adjust_p (gdbarch, 1);
set_gdbarch_decr_pc_after_break (gdbarch, 0);
set_gdbarch_double_bit (gdbarch, 8 * TARGET_CHAR_BIT);
- set_gdbarch_extract_struct_value_address (gdbarch,
- sparc_extract_struct_value_address);
+ set_gdbarch_deprecated_extract_struct_value_address (gdbarch, sparc_extract_struct_value_address);
set_gdbarch_fix_call_dummy (gdbarch, sparc_gdbarch_fix_call_dummy);
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_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_num_args (gdbarch, frame_num_args_unknown);
set_gdbarch_frame_saved_pc (gdbarch, sparc_frame_saved_pc);
set_gdbarch_frameless_function_invocation (gdbarch,
frameless_look_for_prologue);
set_gdbarch_get_saved_register (gdbarch, sparc_get_saved_register);
- set_gdbarch_ieee_float (gdbarch, 1);
set_gdbarch_init_extra_frame_info (gdbarch, sparc_init_extra_frame_info);
set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
set_gdbarch_int_bit (gdbarch, 4 * TARGET_CHAR_BIT);
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);
set_gdbarch_reg_struct_has_addr (gdbarch, sparc_reg_struct_has_addr);
set_gdbarch_return_value_on_stack (gdbarch, sparc_return_value_on_stack);
set_gdbarch_saved_pc_after_call (gdbarch, sparc_saved_pc_after_call);
+ set_gdbarch_prologue_frameless_p (gdbarch, sparc_prologue_frameless_p);
set_gdbarch_short_bit (gdbarch, 2 * TARGET_CHAR_BIT);
- set_gdbarch_skip_prologue (gdbarch, sparc_gdbarch_skip_prologue);
+ set_gdbarch_skip_prologue (gdbarch, sparc_skip_prologue);
set_gdbarch_sp_regnum (gdbarch, SPARC_SP_REGNUM);
- set_gdbarch_use_generic_dummy_frames (gdbarch, 0);
+ set_gdbarch_deprecated_use_generic_dummy_frames (gdbarch, 0);
set_gdbarch_write_pc (gdbarch, generic_target_write_pc);
/*
/* 32-bit machine types: */
#ifdef SPARC32_CALL_DUMMY_ON_STACK
+ set_gdbarch_deprecated_pc_in_call_dummy (gdbarch, deprecated_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);
+
+ /* NOTE: cagney/2002-04-26: Based from info posted by Peter
+ Schauer around Oct '99. Briefly, due to aspects of the SPARC
+ ABI, it isn't possible to use ON_STACK with a strictly
+ compliant compiler.
+
+ Peter Schauer writes ...
+
+ No, any call from GDB to a user function returning a
+ struct/union will fail miserably. Try this:
+
+ *NOINDENT*
+ struct x
+ {
+ int a[4];
+ };
+
+ struct x gx;
+
+ struct x
+ sret ()
+ {
+ return gx;
+ }
+
+ main ()
+ {
+ int i;
+ for (i = 0; i < 4; i++)
+ gx.a[i] = i + 1;
+ gx = sret ();
+ }
+ *INDENT*
+
+ Set a breakpoint at the gx = sret () statement, run to it and
+ issue a `print sret()'. It will not succed with your
+ approach, and I doubt that continuing the program will work
+ as well.
+
+ For details of the ABI see the Sparc Architecture Manual. I
+ have Version 8 (Prentice Hall ISBN 0-13-825001-4) and the
+ calling conventions for functions returning aggregate values
+ are explained in Appendix D.3. */
+
set_gdbarch_call_dummy_location (gdbarch, ON_STACK);
set_gdbarch_call_dummy_words (gdbarch, call_dummy_32);
#else
+ set_gdbarch_deprecated_pc_in_call_dummy (gdbarch, deprecated_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);
- set_gdbarch_call_dummy_location (gdbarch, AT_ENTRY_POINT);
set_gdbarch_call_dummy_words (gdbarch, call_dummy_nil);
#endif
set_gdbarch_call_dummy_stack_adjust (gdbarch, 68);
set_gdbarch_store_struct_return (gdbarch, sparc32_store_struct_return);
set_gdbarch_use_struct_convention (gdbarch,
generic_use_struct_convention);
- set_gdbarch_write_fp (gdbarch, generic_target_write_fp);
set_gdbarch_write_sp (gdbarch, generic_target_write_sp);
tdep->y_regnum = SPARC32_Y_REGNUM;
tdep->fp_max_regnum = SPARC_FP0_REGNUM + 32;
default: /* Any new machine type is likely to be 64-bit. */
#ifdef SPARC64_CALL_DUMMY_ON_STACK
+ set_gdbarch_deprecated_pc_in_call_dummy (gdbarch, deprecated_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_deprecated_pc_in_call_dummy (gdbarch, deprecated_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);
- set_gdbarch_call_dummy_location (gdbarch, AT_ENTRY_POINT);
set_gdbarch_call_dummy_start_offset (gdbarch, 0);
set_gdbarch_call_dummy_words (gdbarch, call_dummy_nil);
#endif
set_gdbarch_store_struct_return (gdbarch, sparc64_store_struct_return);
set_gdbarch_use_struct_convention (gdbarch,
sparc64_use_struct_convention);
- set_gdbarch_write_fp (gdbarch, sparc64_write_fp);
set_gdbarch_write_sp (gdbarch, sparc64_write_sp);
tdep->y_regnum = SPARC64_Y_REGNUM;
tdep->fp_max_regnum = SPARC_FP0_REGNUM + 48;
switch (info.bfd_arch_info->mach)
{
case bfd_mach_sparc:
- set_gdbarch_extract_return_value (gdbarch, sparc32_extract_return_value);
+ set_gdbarch_deprecated_extract_return_value (gdbarch, sparc32_extract_return_value);
set_gdbarch_frame_chain_valid (gdbarch, file_frame_chain_valid);
set_gdbarch_num_regs (gdbarch, 72);
set_gdbarch_register_bytes (gdbarch, 32*4 + 32*4 + 8*4);
set_gdbarch_register_name (gdbarch, sparc32_register_name);
- set_gdbarch_store_return_value (gdbarch, sparc_store_return_value);
+ set_gdbarch_deprecated_store_return_value (gdbarch, sparc_store_return_value);
tdep->has_fpu = 1; /* (all but sparclet and sparclite) */
tdep->fp_register_bytes = 32 * 4;
tdep->print_insn_mach = bfd_mach_sparc;
break;
case bfd_mach_sparc_sparclet:
- set_gdbarch_extract_return_value (gdbarch,
- sparclet_extract_return_value);
+ set_gdbarch_deprecated_extract_return_value (gdbarch, sparclet_extract_return_value);
set_gdbarch_frame_chain_valid (gdbarch, file_frame_chain_valid);
set_gdbarch_num_regs (gdbarch, 32 + 32 + 8 + 8 + 8);
set_gdbarch_register_bytes (gdbarch, 32*4 + 32*4 + 8*4 + 8*4 + 8*4);
set_gdbarch_register_name (gdbarch, sparclet_register_name);
- set_gdbarch_store_return_value (gdbarch, sparclet_store_return_value);
+ set_gdbarch_deprecated_store_return_value (gdbarch, sparclet_store_return_value);
tdep->has_fpu = 0; /* (all but sparclet and sparclite) */
tdep->fp_register_bytes = 0;
tdep->print_insn_mach = bfd_mach_sparc_sparclet;
break;
case bfd_mach_sparc_sparclite:
- set_gdbarch_extract_return_value (gdbarch, sparc32_extract_return_value);
+ set_gdbarch_deprecated_extract_return_value (gdbarch, sparc32_extract_return_value);
set_gdbarch_frame_chain_valid (gdbarch, func_frame_chain_valid);
set_gdbarch_num_regs (gdbarch, 80);
set_gdbarch_register_bytes (gdbarch, 32*4 + 32*4 + 8*4 + 8*4);
set_gdbarch_register_name (gdbarch, sparclite_register_name);
- set_gdbarch_store_return_value (gdbarch, sparc_store_return_value);
+ set_gdbarch_deprecated_store_return_value (gdbarch, sparc_store_return_value);
tdep->has_fpu = 0; /* (all but sparclet and sparclite) */
tdep->fp_register_bytes = 0;
tdep->print_insn_mach = bfd_mach_sparc_sparclite;
break;
case bfd_mach_sparc_v8plus:
- set_gdbarch_extract_return_value (gdbarch, sparc32_extract_return_value);
+ set_gdbarch_deprecated_extract_return_value (gdbarch, sparc32_extract_return_value);
set_gdbarch_frame_chain_valid (gdbarch, file_frame_chain_valid);
set_gdbarch_num_regs (gdbarch, 72);
set_gdbarch_register_bytes (gdbarch, 32*4 + 32*4 + 8*4);
set_gdbarch_register_name (gdbarch, sparc32_register_name);
- set_gdbarch_store_return_value (gdbarch, sparc_store_return_value);
+ set_gdbarch_deprecated_store_return_value (gdbarch, sparc_store_return_value);
tdep->print_insn_mach = bfd_mach_sparc;
tdep->fp_register_bytes = 32 * 4;
tdep->has_fpu = 1; /* (all but sparclet and sparclite) */
break;
case bfd_mach_sparc_v8plusa:
- set_gdbarch_extract_return_value (gdbarch, sparc32_extract_return_value);
+ set_gdbarch_deprecated_extract_return_value (gdbarch, sparc32_extract_return_value);
set_gdbarch_frame_chain_valid (gdbarch, file_frame_chain_valid);
set_gdbarch_num_regs (gdbarch, 72);
set_gdbarch_register_bytes (gdbarch, 32*4 + 32*4 + 8*4);
set_gdbarch_register_name (gdbarch, sparc32_register_name);
- set_gdbarch_store_return_value (gdbarch, sparc_store_return_value);
+ set_gdbarch_deprecated_store_return_value (gdbarch, sparc_store_return_value);
tdep->has_fpu = 1; /* (all but sparclet and sparclite) */
tdep->fp_register_bytes = 32 * 4;
tdep->print_insn_mach = bfd_mach_sparc;
break;
case bfd_mach_sparc_sparclite_le:
- set_gdbarch_extract_return_value (gdbarch, sparc32_extract_return_value);
+ set_gdbarch_deprecated_extract_return_value (gdbarch, sparc32_extract_return_value);
set_gdbarch_frame_chain_valid (gdbarch, func_frame_chain_valid);
set_gdbarch_num_regs (gdbarch, 80);
set_gdbarch_register_bytes (gdbarch, 32*4 + 32*4 + 8*4 + 8*4);
set_gdbarch_register_name (gdbarch, sparclite_register_name);
- set_gdbarch_store_return_value (gdbarch, sparc_store_return_value);
+ set_gdbarch_deprecated_store_return_value (gdbarch, sparc_store_return_value);
tdep->has_fpu = 0; /* (all but sparclet and sparclite) */
tdep->fp_register_bytes = 0;
tdep->print_insn_mach = bfd_mach_sparc_sparclite;
break;
case bfd_mach_sparc_v9:
- set_gdbarch_extract_return_value (gdbarch, sparc64_extract_return_value);
+ set_gdbarch_deprecated_extract_return_value (gdbarch, sparc64_extract_return_value);
set_gdbarch_frame_chain_valid (gdbarch, file_frame_chain_valid);
set_gdbarch_num_regs (gdbarch, 125);
set_gdbarch_register_bytes (gdbarch, 32*8 + 32*8 + 45*8);
set_gdbarch_register_name (gdbarch, sparc64_register_name);
- set_gdbarch_store_return_value (gdbarch, sparc_store_return_value);
+ set_gdbarch_deprecated_store_return_value (gdbarch, sparc_store_return_value);
tdep->has_fpu = 1; /* (all but sparclet and sparclite) */
tdep->fp_register_bytes = 64 * 4;
tdep->print_insn_mach = bfd_mach_sparc_v9a;
break;
case bfd_mach_sparc_v9a:
- set_gdbarch_extract_return_value (gdbarch, sparc64_extract_return_value);
+ set_gdbarch_deprecated_extract_return_value (gdbarch, sparc64_extract_return_value);
set_gdbarch_frame_chain_valid (gdbarch, file_frame_chain_valid);
set_gdbarch_num_regs (gdbarch, 125);
set_gdbarch_register_bytes (gdbarch, 32*8 + 32*8 + 45*8);
set_gdbarch_register_name (gdbarch, sparc64_register_name);
- set_gdbarch_store_return_value (gdbarch, sparc_store_return_value);
+ set_gdbarch_deprecated_store_return_value (gdbarch, sparc_store_return_value);
tdep->has_fpu = 1; /* (all but sparclet and sparclite) */
tdep->fp_register_bytes = 64 * 4;
tdep->print_insn_mach = bfd_mach_sparc_v9a;
break;
}
+ /* Hook in OS ABI-specific overrides, if they have been registered. */
+ gdbarch_init_osabi (info, gdbarch, osabi);
+
return gdbarch;
}
+static void
+sparc_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, "sparc_dump_tdep: OS ABI = %s\n",
+ gdbarch_osabi_name (tdep->osabi));
+}