/* Target-dependent code for the SPARC for GDB, the GNU debugger.
- Copyright 1986, 1987, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
- 1997, 1998, 1999, 2000, 2001 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>
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. */
it later. */
if (fi->next->next != NULL
&& (fi->next->next->signal_handler_caller
- || frame_in_dummy (fi->next->next))
+ || deprecated_frame_in_dummy (fi->next->next))
&& frameless_look_for_prologue (fi->next))
{
/* A frameless function interrupted by a signal did not change
else if (frame->extra_info->in_prologue ||
(frame->next != NULL &&
(frame->next->signal_handler_caller ||
- frame_in_dummy (frame->next)) &&
+ deprecated_frame_in_dummy (frame->next)) &&
frameless_look_for_prologue (frame)))
{
/* A frameless function interrupted by a signal did not save
return pc;
}
+/* Advance PC across any function entry prologue instructions to reach
+ some "real" code. */
+
CORE_ADDR
-sparc_skip_prologue (CORE_ADDR start_pc, int frameless_p)
+sparc_skip_prologue (CORE_ADDR start_pc)
{
- return examine_prologue (start_pc, frameless_p, NULL, NULL);
+ 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 ip == examine_prologue (ip, 1, NULL, NULL);
}
/* Check instruction at ADDR to see if it is a branch.
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)
{
/* 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;
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);
}
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))
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
}
}
#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
Pretty print various registers. */
/* FIXME: Would be nice if this did some fancy things for 32 bit sparc. */
-void
+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 (selected_frame, regno, value)
+ && frame_register_read (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 (selected_frame, regno + 2, value + 8)
+ && frame_register_read (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 (selected_frame, regno, value)
+ && frame_register_read (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, 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, selected_frame,
+ regnum, all);
+}
+
\f
int
gdb_print_insn_sparc (bfd_vma memaddr, disassemble_info *info)
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;
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));
}
if (ap->mach == bfd_mach_sparc_sparclite_le)
{
- if (TARGET_BYTE_ORDER_SELECTABLE_P)
- {
- target_byte_order = BFD_ENDIAN_LITTLE;
- 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 (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 */
write_register (SP_REGNUM, val);
}
-void
-sparc64_write_fp (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),
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;
}
}
/* 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
{
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_arch_info->arch != bfd_arch_sparc)
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_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_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_write_pc (gdbarch, generic_target_write_pc);
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_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;
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));
+}