/* Target-dependent code for SPARC.
- Copyright (C) 2003-2014 Free Software Foundation, Inc.
+ Copyright (C) 2003-2022 Free Software Foundation, Inc.
This file is part of GDB.
#include "defs.h"
#include "arch-utils.h"
#include "dis-asm.h"
-#include "dwarf2-frame.h"
-#include "floatformat.h"
+#include "dwarf2.h"
+#include "dwarf2/frame.h"
#include "frame.h"
#include "frame-base.h"
#include "frame-unwind.h"
#include "osabi.h"
#include "regcache.h"
#include "target.h"
+#include "target-descriptions.h"
#include "value.h"
-#include "gdb_assert.h"
-#include <string.h>
-
#include "sparc-tdep.h"
#include "sparc-ravenscar-thread.h"
+#include <algorithm>
struct regset;
#define X_DISP19(i) ((((i) & 0x7ffff) ^ 0x40000) - 0x40000)
#define X_DISP10(i) ((((((i) >> 11) && 0x300) | (((i) >> 5) & 0xff)) ^ 0x200) - 0x200)
#define X_SIMM13(i) ((((i) & 0x1fff) ^ 0x1000) - 0x1000)
+/* Macros to identify some instructions. */
+/* RETURN (RETT in V8) */
+#define X_RETTURN(i) ((X_OP (i) == 0x2) && (X_OP3 (i) == 0x39))
/* Fetch the instruction at PC. Instructions are always big-endian
even if the processor operates in little-endian mode. */
OP2=5: Branch on FP Condition Codes with Prediction (FBfcc).
OP2=6: Branch on FP Condition Codes (FBcc).
OP2=3 && Bit28=0:
- Branch on Integer Register with Prediction (BPr).
+ Branch on Integer Register with Prediction (BPr).
This leaves out ILLTRAP (OP2=0), SETHI/NOP (OP2=4) and the V8
coprocessor branch instructions (Op2=7). */
sparc_fetch_wcookie (struct gdbarch *gdbarch)
{
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- struct target_ops *ops = ¤t_target;
+ struct target_ops *ops = current_inferior ()->top_target ();
gdb_byte buf[8];
int len;
{
int len = TYPE_LENGTH (type);
- switch (TYPE_CODE (type))
+ switch (type->code ())
{
case TYPE_CODE_INT:
case TYPE_CODE_BOOL:
return (len == 1 || len == 2 || len == 4 || len == 8);
case TYPE_CODE_PTR:
case TYPE_CODE_REF:
+ case TYPE_CODE_RVALUE_REF:
/* Allow either 32-bit or 64-bit pointers. */
return (len == 4 || len == 8);
default:
static int
sparc_floating_p (const struct type *type)
{
- switch (TYPE_CODE (type))
+ switch (type->code ())
{
case TYPE_CODE_FLT:
{
static int
sparc_complex_floating_p (const struct type *type)
{
- switch (TYPE_CODE (type))
+ switch (type->code ())
{
case TYPE_CODE_COMPLEX:
{
static int
sparc_structure_or_union_p (const struct type *type)
{
- switch (TYPE_CODE (type))
+ switch (type->code ())
{
case TYPE_CODE_STRUCT:
case TYPE_CODE_UNION:
return 0;
}
-/* Register information. */
+/* Return true if TYPE is returned by memory, false if returned by
+ register. */
+
+static bool
+sparc_structure_return_p (const struct type *type)
+{
+ if (type->code () == TYPE_CODE_ARRAY && type->is_vector ())
+ {
+ /* Float vectors are always returned by memory. */
+ if (sparc_floating_p (check_typedef (TYPE_TARGET_TYPE (type))))
+ return true;
+ /* Integer vectors are returned by memory if the vector size
+ is greater than 8 bytes long. */
+ return (TYPE_LENGTH (type) > 8);
+ }
+
+ if (sparc_floating_p (type))
+ {
+ /* Floating point types are passed by register for size 4 and
+ 8 bytes, and by memory for size 16 bytes. */
+ return (TYPE_LENGTH (type) == 16);
+ }
+
+ /* Other than that, only aggregates of all sizes get returned by
+ memory. */
+ return sparc_structure_or_union_p (type);
+}
-static const char *sparc32_register_names[] =
+/* Return true if arguments of the given TYPE are passed by
+ memory; false if returned by register. */
+
+static bool
+sparc_arg_by_memory_p (const struct type *type)
{
- "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
- "o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7",
- "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
- "i0", "i1", "i2", "i3", "i4", "i5", "fp", "i7",
+ if (type->code () == TYPE_CODE_ARRAY && type->is_vector ())
+ {
+ /* Float vectors are always passed by memory. */
+ if (sparc_floating_p (check_typedef (TYPE_TARGET_TYPE (type))))
+ return true;
+ /* Integer vectors are passed by memory if the vector size
+ is greater than 8 bytes long. */
+ return (TYPE_LENGTH (type) > 8);
+ }
- "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
- "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
- "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
- "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
+ /* Floats are passed by register for size 4 and 8 bytes, and by memory
+ for size 16 bytes. */
+ if (sparc_floating_p (type))
+ return (TYPE_LENGTH (type) == 16);
+ /* Complex floats and aggregates of all sizes are passed by memory. */
+ if (sparc_complex_floating_p (type) || sparc_structure_or_union_p (type))
+ return true;
+
+ /* Everything else gets passed by register. */
+ return false;
+}
+
+/* Register information. */
+#define SPARC32_FPU_REGISTERS \
+ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
+ "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \
+ "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", \
+ "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31"
+#define SPARC32_CP0_REGISTERS \
"y", "psr", "wim", "tbr", "pc", "npc", "fsr", "csr"
+
+static const char * const sparc_core_register_names[] = {
+ SPARC_CORE_REGISTERS
+};
+static const char * const sparc32_fpu_register_names[] = {
+ SPARC32_FPU_REGISTERS
+};
+static const char * const sparc32_cp0_register_names[] = {
+ SPARC32_CP0_REGISTERS
+};
+
+static const char * const sparc32_register_names[] =
+{
+ SPARC_CORE_REGISTERS,
+ SPARC32_FPU_REGISTERS,
+ SPARC32_CP0_REGISTERS
};
/* Total number of registers. */
/* We provide the aliases %d0..%d30 for the floating registers as
"psuedo" registers. */
-static const char *sparc32_pseudo_register_names[] =
+static const char * const sparc32_pseudo_register_names[] =
{
"d0", "d2", "d4", "d6", "d8", "d10", "d12", "d14",
"d16", "d18", "d20", "d22", "d24", "d26", "d28", "d30"
/* Total number of pseudo registers. */
#define SPARC32_NUM_PSEUDO_REGS ARRAY_SIZE (sparc32_pseudo_register_names)
+/* Return the name of pseudo register REGNUM. */
+
+static const char *
+sparc32_pseudo_register_name (struct gdbarch *gdbarch, int regnum)
+{
+ regnum -= gdbarch_num_regs (gdbarch);
+
+ if (regnum < SPARC32_NUM_PSEUDO_REGS)
+ return sparc32_pseudo_register_names[regnum];
+
+ internal_error (__FILE__, __LINE__,
+ _("sparc32_pseudo_register_name: bad register number %d"),
+ regnum);
+}
+
/* Return the name of register REGNUM. */
static const char *
sparc32_register_name (struct gdbarch *gdbarch, int regnum)
{
- if (regnum >= 0 && regnum < SPARC32_NUM_REGS)
- return sparc32_register_names[regnum];
+ if (tdesc_has_registers (gdbarch_target_desc (gdbarch)))
+ return tdesc_register_name (gdbarch, regnum);
- if (regnum < SPARC32_NUM_REGS + SPARC32_NUM_PSEUDO_REGS)
- return sparc32_pseudo_register_names[regnum - SPARC32_NUM_REGS];
+ if (regnum >= 0 && regnum < gdbarch_num_regs (gdbarch))
+ return sparc32_register_names[regnum];
- return NULL;
+ return sparc32_pseudo_register_name (gdbarch, regnum);
}
\f
/* Construct types for ISA-specific registers. */
static struct type *
sparc_psr_type (struct gdbarch *gdbarch)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ sparc_gdbarch_tdep *tdep = (sparc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
if (!tdep->sparc_psr_type)
{
struct type *type;
- type = arch_flags_type (gdbarch, "builtin_type_sparc_psr", 4);
+ type = arch_flags_type (gdbarch, "builtin_type_sparc_psr", 32);
append_flags_type_flag (type, 5, "ET");
append_flags_type_flag (type, 6, "PS");
append_flags_type_flag (type, 7, "S");
static struct type *
sparc_fsr_type (struct gdbarch *gdbarch)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ sparc_gdbarch_tdep *tdep = (sparc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
if (!tdep->sparc_fsr_type)
{
struct type *type;
- type = arch_flags_type (gdbarch, "builtin_type_sparc_fsr", 4);
+ type = arch_flags_type (gdbarch, "builtin_type_sparc_fsr", 32);
append_flags_type_flag (type, 0, "NXA");
append_flags_type_flag (type, 1, "DZA");
append_flags_type_flag (type, 2, "UFA");
return tdep->sparc_fsr_type;
}
+/* Return the GDB type object for the "standard" data type of data in
+ pseudo register REGNUM. */
+
+static struct type *
+sparc32_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
+{
+ regnum -= gdbarch_num_regs (gdbarch);
+
+ if (regnum >= SPARC32_D0_REGNUM && regnum <= SPARC32_D30_REGNUM)
+ return builtin_type (gdbarch)->builtin_double;
+
+ internal_error (__FILE__, __LINE__,
+ _("sparc32_pseudo_register_type: bad register number %d"),
+ regnum);
+}
+
/* Return the GDB type object for the "standard" data type of data in
register REGNUM. */
static struct type *
sparc32_register_type (struct gdbarch *gdbarch, int regnum)
{
+ if (tdesc_has_registers (gdbarch_target_desc (gdbarch)))
+ return tdesc_register_type (gdbarch, regnum);
+
if (regnum >= SPARC_F0_REGNUM && regnum <= SPARC_F31_REGNUM)
return builtin_type (gdbarch)->builtin_float;
- if (regnum >= SPARC32_D0_REGNUM && regnum <= SPARC32_D30_REGNUM)
- return builtin_type (gdbarch)->builtin_double;
-
if (regnum == SPARC_SP_REGNUM || regnum == SPARC_FP_REGNUM)
return builtin_type (gdbarch)->builtin_data_ptr;
if (regnum == SPARC32_FSR_REGNUM)
return sparc_fsr_type (gdbarch);
+ if (regnum >= gdbarch_num_regs (gdbarch))
+ return sparc32_pseudo_register_type (gdbarch, regnum);
+
return builtin_type (gdbarch)->builtin_int32;
}
static enum register_status
sparc32_pseudo_register_read (struct gdbarch *gdbarch,
- struct regcache *regcache,
+ readable_regcache *regcache,
int regnum, gdb_byte *buf)
{
enum register_status status;
+ regnum -= gdbarch_num_regs (gdbarch);
gdb_assert (regnum >= SPARC32_D0_REGNUM && regnum <= SPARC32_D30_REGNUM);
regnum = SPARC_F0_REGNUM + 2 * (regnum - SPARC32_D0_REGNUM);
- status = regcache_raw_read (regcache, regnum, buf);
+ status = regcache->raw_read (regnum, buf);
if (status == REG_VALID)
- status = regcache_raw_read (regcache, regnum + 1, buf + 4);
+ status = regcache->raw_read (regnum + 1, buf + 4);
return status;
}
struct regcache *regcache,
int regnum, const gdb_byte *buf)
{
+ regnum -= gdbarch_num_regs (gdbarch);
gdb_assert (regnum >= SPARC32_D0_REGNUM && regnum <= SPARC32_D30_REGNUM);
regnum = SPARC_F0_REGNUM + 2 * (regnum - SPARC32_D0_REGNUM);
- regcache_raw_write (regcache, regnum, buf);
- regcache_raw_write (regcache, regnum + 1, buf + 4);
+ regcache->raw_write (regnum, buf);
+ regcache->raw_write (regnum + 1, buf + 4);
+}
+\f
+/* Implement the stack_frame_destroyed_p gdbarch method. */
+
+int
+sparc_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc)
+{
+ /* This function must return true if we are one instruction after an
+ instruction that destroyed the stack frame of the current
+ function. The SPARC instructions used to restore the callers
+ stack frame are RESTORE and RETURN/RETT.
+
+ Of these RETURN/RETT is a branch instruction and thus we return
+ true if we are in its delay slot.
+
+ RESTORE is almost always found in the delay slot of a branch
+ instruction that transfers control to the caller, such as JMPL.
+ Thus the next instruction is in the caller frame and we don't
+ need to do anything about it. */
+
+ unsigned int insn = sparc_fetch_instruction (pc - 4);
+
+ return X_RETTURN (insn);
}
\f
static CORE_ADDR
sparc32_store_arguments (struct regcache *regcache, int nargs,
struct value **args, CORE_ADDR sp,
- int struct_return, CORE_ADDR struct_addr)
+ function_call_return_method return_method,
+ CORE_ADDR struct_addr)
{
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ struct gdbarch *gdbarch = regcache->arch ();
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
/* Number of words in the "parameter array". */
int num_elements = 0;
struct type *type = value_type (args[i]);
int len = TYPE_LENGTH (type);
- if (sparc_structure_or_union_p (type)
- || (sparc_floating_p (type) && len == 16)
- || sparc_complex_floating_p (type))
+ if (sparc_arg_by_memory_p (type))
{
/* Structure, Union and Quad-Precision Arguments. */
sp -= len;
/* Use doubleword alignment for these values. That's always
- correct, and wasting a few bytes shouldn't be a problem. */
+ correct, and wasting a few bytes shouldn't be a problem. */
sp &= ~0x7;
- write_memory (sp, value_contents (args[i]), len);
+ write_memory (sp, value_contents (args[i]).data (), len);
args[i] = value_from_pointer (lookup_pointer_type (type), sp);
num_elements++;
}
}
else
{
- /* Integral and pointer arguments. */
- gdb_assert (sparc_integral_or_pointer_p (type));
-
- if (len < 4)
- args[i] = value_cast (builtin_type (gdbarch)->builtin_int32,
- args[i]);
+ /* Arguments passed via the General Purpose Registers. */
num_elements += ((len + 3) / 4);
}
}
/* Always allocate at least six words. */
- sp -= max (6, num_elements) * 4;
+ sp -= std::max (6, num_elements) * 4;
/* The psABI says that "Software convention requires space for the
struct/union return value pointer, even if the word is unused." */
for (i = 0; i < nargs; i++)
{
- const bfd_byte *valbuf = value_contents (args[i]);
+ const bfd_byte *valbuf = value_contents (args[i]).data ();
struct type *type = value_type (args[i]);
int len = TYPE_LENGTH (type);
+ gdb_byte buf[4];
+
+ if (len < 4)
+ {
+ memset (buf, 0, 4 - len);
+ memcpy (buf + 4 - len, valbuf, len);
+ valbuf = buf;
+ len = 4;
+ }
gdb_assert (len == 4 || len == 8);
{
int regnum = SPARC_O0_REGNUM + element;
- regcache_cooked_write (regcache, regnum, valbuf);
+ regcache->cooked_write (regnum, valbuf);
if (len > 4 && element < 5)
- regcache_cooked_write (regcache, regnum + 1, valbuf + 4);
+ regcache->cooked_write (regnum + 1, valbuf + 4);
}
/* Always store the argument in memory. */
gdb_assert (element == num_elements);
- if (struct_return)
+ if (return_method == return_method_struct)
{
gdb_byte buf[4];
sparc32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
struct regcache *regcache, CORE_ADDR bp_addr,
int nargs, struct value **args, CORE_ADDR sp,
- int struct_return, CORE_ADDR struct_addr)
+ function_call_return_method return_method,
+ CORE_ADDR struct_addr)
{
- CORE_ADDR call_pc = (struct_return ? (bp_addr - 12) : (bp_addr - 8));
+ CORE_ADDR call_pc = (return_method == return_method_struct
+ ? (bp_addr - 12) : (bp_addr - 8));
/* Set return address. */
regcache_cooked_write_unsigned (regcache, SPARC_O7_REGNUM, call_pc);
/* Set up function arguments. */
- sp = sparc32_store_arguments (regcache, nargs, args, sp,
- struct_return, struct_addr);
+ sp = sparc32_store_arguments (regcache, nargs, args, sp, return_method,
+ struct_addr);
/* Allocate the 16-word window save area. */
sp -= 16 * 4;
encode a breakpoint instruction, store the length of the string in
*LEN and optionally adjust *PC to point to the correct memory
location for inserting the breakpoint. */
-
-static const gdb_byte *
-sparc_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pc, int *len)
-{
- static const gdb_byte break_insn[] = { 0x91, 0xd0, 0x20, 0x01 };
+constexpr gdb_byte sparc_break_insn[] = { 0x91, 0xd0, 0x20, 0x01 };
- *len = sizeof (break_insn);
- return break_insn;
-}
+typedef BP_MANIPULATION (sparc_break_insn) sparc_breakpoint;
\f
/* Allocate and initialize a frame cache. */
{
CORE_ADDR pc = start_pc;
unsigned long insn;
- int offset_stack_checking_sequence = 0;
int probing_loop = 0;
/* With GCC, all stack checking sequences begin with the same two
instructions, plus an optional one in the case of a probing loop:
- sethi <some immediate>, %g1
- sub %sp, %g1, %g1
+ sethi <some immediate>, %g1
+ sub %sp, %g1, %g1
or:
- sethi <some immediate>, %g1
- sethi <some immediate>, %g4
- sub %sp, %g1, %g1
+ sethi <some immediate>, %g1
+ sethi <some immediate>, %g4
+ sub %sp, %g1, %g1
or:
- sethi <some immediate>, %g1
- sub %sp, %g1, %g1
- sethi <some immediate>, %g4
+ sethi <some immediate>, %g1
+ sub %sp, %g1, %g1
+ sethi <some immediate>, %g4
If the optional instruction is found (setting g4), assume that a
probing loop will follow. */
/* sub %sp, %g1, %g1 */
if (!(X_OP (insn) == 2 && X_OP3 (insn) == 0x4 && !X_I(insn)
- && X_RD (insn) == 1 && X_RS1 (insn) == 14 && X_RS2 (insn) == 1))
+ && X_RD (insn) == 1 && X_RS1 (insn) == 14 && X_RS2 (insn) == 1))
return start_pc;
insn = sparc_fetch_instruction (pc);
}
/* First possible sequence:
- [first two instructions above]
- clr [%g1 - some immediate] */
+ [first two instructions above]
+ clr [%g1 - some immediate] */
/* clr [%g1 - some immediate] */
if (X_OP (insn) == 3 && X_OP3(insn) == 0x4 && X_I(insn)
}
/* Second possible sequence: A small number of probes.
- [first two instructions above]
- clr [%g1]
- add %g1, -<some immediate>, %g1
- clr [%g1]
- [repeat the two instructions above any (small) number of times]
- clr [%g1 - some immediate] */
+ [first two instructions above]
+ clr [%g1]
+ add %g1, -<some immediate>, %g1
+ clr [%g1]
+ [repeat the two instructions above any (small) number of times]
+ clr [%g1 - some immediate] */
/* clr [%g1] */
else if (X_OP (insn) == 3 && X_OP3(insn) == 0x4 && !X_I(insn)
&& X_RS1 (insn) == 1 && X_RD (insn) == 0)
{
while (1)
- {
- /* add %g1, -<some immediate>, %g1 */
- insn = sparc_fetch_instruction (pc);
- pc = pc + 4;
- if (!(X_OP (insn) == 2 && X_OP3(insn) == 0 && X_I(insn)
- && X_RS1 (insn) == 1 && X_RD (insn) == 1))
- break;
-
- /* clr [%g1] */
- insn = sparc_fetch_instruction (pc);
- pc = pc + 4;
- if (!(X_OP (insn) == 3 && X_OP3(insn) == 0x4 && !X_I(insn)
- && X_RD (insn) == 0 && X_RS1 (insn) == 1))
- return start_pc;
- }
+ {
+ /* add %g1, -<some immediate>, %g1 */
+ insn = sparc_fetch_instruction (pc);
+ pc = pc + 4;
+ if (!(X_OP (insn) == 2 && X_OP3(insn) == 0 && X_I(insn)
+ && X_RS1 (insn) == 1 && X_RD (insn) == 1))
+ break;
+
+ /* clr [%g1] */
+ insn = sparc_fetch_instruction (pc);
+ pc = pc + 4;
+ if (!(X_OP (insn) == 3 && X_OP3(insn) == 0x4 && !X_I(insn)
+ && X_RD (insn) == 0 && X_RS1 (insn) == 1))
+ return start_pc;
+ }
/* clr [%g1 - some immediate] */
if (!(X_OP (insn) == 3 && X_OP3(insn) == 0x4 && X_I(insn)
- && X_RS1 (insn) == 1 && X_RD (insn) == 0))
- return start_pc;
+ && X_RS1 (insn) == 1 && X_RD (insn) == 0))
+ return start_pc;
/* We found a valid stack-check sequence, return the new PC. */
return pc;
}
/* Third sequence: A probing loop.
- [first three instructions above]
- sub %g1, %g4, %g4
- cmp %g1, %g4
- be <disp>
- add %g1, -<some immediate>, %g1
- ba <disp>
- clr [%g1]
+ [first three instructions above]
+ sub %g1, %g4, %g4
+ cmp %g1, %g4
+ be <disp>
+ add %g1, -<some immediate>, %g1
+ ba <disp>
+ clr [%g1]
And an optional last probe for the remainder:
- clr [%g4 - some immediate] */
+ clr [%g4 - some immediate] */
if (probing_loop)
{
/* sub %g1, %g4, %g4 */
if (!(X_OP (insn) == 2 && X_OP3 (insn) == 0x4 && !X_I(insn)
- && X_RD (insn) == 4 && X_RS1 (insn) == 1 && X_RS2 (insn) == 4))
- return start_pc;
+ && X_RD (insn) == 4 && X_RS1 (insn) == 1 && X_RS2 (insn) == 4))
+ return start_pc;
/* cmp %g1, %g4 */
insn = sparc_fetch_instruction (pc);
pc = pc + 4;
if (!(X_OP (insn) == 2 && X_OP3 (insn) == 0x14 && !X_I(insn)
- && X_RD (insn) == 0 && X_RS1 (insn) == 1 && X_RS2 (insn) == 4))
- return start_pc;
+ && X_RD (insn) == 0 && X_RS1 (insn) == 1 && X_RS2 (insn) == 4))
+ return start_pc;
/* be <disp> */
insn = sparc_fetch_instruction (pc);
pc = pc + 4;
if (!(X_OP (insn) == 0 && X_COND (insn) == 0x1))
- return start_pc;
+ return start_pc;
/* add %g1, -<some immediate>, %g1 */
insn = sparc_fetch_instruction (pc);
pc = pc + 4;
if (!(X_OP (insn) == 2 && X_OP3(insn) == 0 && X_I(insn)
- && X_RS1 (insn) == 1 && X_RD (insn) == 1))
- return start_pc;
+ && X_RS1 (insn) == 1 && X_RD (insn) == 1))
+ return start_pc;
/* ba <disp> */
insn = sparc_fetch_instruction (pc);
pc = pc + 4;
if (!(X_OP (insn) == 0 && X_COND (insn) == 0x8))
- return start_pc;
+ return start_pc;
/* clr [%g1] (st %g0, [%g1] or st %g0, [%g1+0]) */
insn = sparc_fetch_instruction (pc);
pc = pc + 4;
if (!(X_OP (insn) == 3 && X_OP3(insn) == 0x4
- && X_RD (insn) == 0 && X_RS1 (insn) == 1
+ && X_RD (insn) == 0 && X_RS1 (insn) == 1
&& (!X_I(insn) || X_SIMM13 (insn) == 0)))
- return start_pc;
+ return start_pc;
/* We found a valid stack-check sequence, return the new PC. */
insn = sparc_fetch_instruction (pc);
pc = pc + 4;
if (!(X_OP (insn) == 3 && X_OP3(insn) == 0x4 && X_I(insn)
- && X_RS1 (insn) == 4 && X_RD (insn) == 0))
- return pc - 4;
+ && X_RS1 (insn) == 4 && X_RD (insn) == 0))
+ return pc - 4;
else
return pc;
}
sparc_analyze_prologue (struct gdbarch *gdbarch, CORE_ADDR pc,
CORE_ADDR current_pc, struct sparc_frame_cache *cache)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ sparc_gdbarch_tdep *tdep = (sparc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
unsigned long insn;
int offset = 0;
int dest = -1;
return pc;
}
-static CORE_ADDR
-sparc_unwind_pc (struct gdbarch *gdbarch, struct frame_info *this_frame)
-{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
- return frame_unwind_register_unsigned (this_frame, tdep->pc_regnum);
-}
-
/* Return PC of first real instruction of the function starting at
START_PC. */
sparc32_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc)
{
struct symtab_and_line sal;
- CORE_ADDR func_start, func_end;
+ CORE_ADDR func_addr;
struct sparc_frame_cache cache;
/* 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))
+
+ if (find_pc_partial_function (start_pc, NULL, &func_addr, NULL))
{
- sal = find_pc_line (func_start, 0);
+ CORE_ADDR post_prologue_pc
+ = skip_prologue_using_sal (gdbarch, func_addr);
- if (sal.end < func_end
- && start_pc <= sal.end)
- return sal.end;
+ if (post_prologue_pc != 0)
+ return std::max (start_pc, post_prologue_pc);
}
start_pc = sparc_analyze_prologue (gdbarch, start_pc, 0xffffffffUL, &cache);
struct sparc_frame_cache *cache;
if (*this_cache)
- return *this_cache;
+ return (struct sparc_frame_cache *) *this_cache;
cache = sparc_alloc_frame_cache ();
*this_cache = cache;
if (cache->frameless_p)
{
/* This function is frameless, so %fp (%i6) holds the frame
- pointer for our calling frame. Use %sp (%o6) as this frame's
- base address. */
+ pointer for our calling frame. Use %sp (%o6) as this frame's
+ base address. */
cache->base =
- get_frame_register_unsigned (this_frame, SPARC_SP_REGNUM);
+ get_frame_register_unsigned (this_frame, SPARC_SP_REGNUM);
}
else
{
/* For normal frames, %fp (%i6) holds the frame pointer, the
- base address for the current stack frame. */
+ base address for the current stack frame. */
cache->base =
get_frame_register_unsigned (this_frame, SPARC_FP_REGNUM);
}
sparc32_struct_return_from_sym (struct symbol *sym)
{
struct type *type = check_typedef (SYMBOL_TYPE (sym));
- enum type_code code = TYPE_CODE (type);
+ enum type_code code = type->code ();
if (code == TYPE_CODE_FUNC || code == TYPE_CODE_METHOD)
{
struct symbol *sym;
if (*this_cache)
- return *this_cache;
+ return (struct sparc_frame_cache *) *this_cache;
cache = sparc_frame_cache (this_frame, this_cache);
else
{
/* There is no debugging information for this function to
- help us determine whether this function returns a struct
- or not. So we rely on another heuristic which is to check
- the instruction at the return address and see if this is
- an "unimp" instruction. If it is, then it is a struct-return
- function. */
+ help us determine whether this function returns a struct
+ or not. So we rely on another heuristic which is to check
+ the instruction at the return address and see if this is
+ an "unimp" instruction. If it is, then it is a struct-return
+ function. */
CORE_ADDR pc;
int regnum =
(cache->copied_regs_mask & 0x80) ? SPARC_I7_REGNUM : SPARC_O7_REGNUM;
pc = get_frame_register_unsigned (this_frame, regnum) + 8;
if (sparc_is_unimp_insn (pc))
- cache->struct_return_p = 1;
+ cache->struct_return_p = 1;
}
return cache;
if (wcookie != 0 && !cache->frameless_p && regnum == SPARC_I7_REGNUM)
{
- CORE_ADDR addr = cache->base + (regnum - SPARC_L0_REGNUM) * 4;
- ULONGEST i7;
+ CORE_ADDR addr = cache->base + (regnum - SPARC_L0_REGNUM) * 4;
+ ULONGEST i7;
- /* Read the value in from memory. */
- i7 = get_frame_memory_unsigned (this_frame, addr, 4);
- return frame_unwind_got_constant (this_frame, regnum, i7 ^ wcookie);
+ /* Read the value in from memory. */
+ i7 = get_frame_memory_unsigned (this_frame, addr, 4);
+ return frame_unwind_got_constant (this_frame, regnum, i7 ^ wcookie);
}
}
static const struct frame_unwind sparc32_frame_unwind =
{
+ "sparc32 prologue",
NORMAL_FRAME,
default_frame_unwind_stop_reason,
sparc32_frame_this_id,
int len = TYPE_LENGTH (type);
gdb_byte buf[32];
- gdb_assert (!sparc_structure_or_union_p (type));
- gdb_assert (!(sparc_floating_p (type) && len == 16));
+ gdb_assert (!sparc_structure_return_p (type));
- if (sparc_floating_p (type) || sparc_complex_floating_p (type))
+ if (sparc_floating_p (type) || sparc_complex_floating_p (type)
+ || type->code () == TYPE_CODE_ARRAY)
{
/* Floating return values. */
- regcache_cooked_read (regcache, SPARC_F0_REGNUM, buf);
+ regcache->cooked_read (SPARC_F0_REGNUM, buf);
if (len > 4)
- regcache_cooked_read (regcache, SPARC_F1_REGNUM, buf + 4);
+ regcache->cooked_read (SPARC_F1_REGNUM, buf + 4);
if (len > 8)
{
- regcache_cooked_read (regcache, SPARC_F2_REGNUM, buf + 8);
- regcache_cooked_read (regcache, SPARC_F3_REGNUM, buf + 12);
+ regcache->cooked_read (SPARC_F2_REGNUM, buf + 8);
+ regcache->cooked_read (SPARC_F3_REGNUM, buf + 12);
}
if (len > 16)
{
- regcache_cooked_read (regcache, SPARC_F4_REGNUM, buf + 16);
- regcache_cooked_read (regcache, SPARC_F5_REGNUM, buf + 20);
- regcache_cooked_read (regcache, SPARC_F6_REGNUM, buf + 24);
- regcache_cooked_read (regcache, SPARC_F7_REGNUM, buf + 28);
+ regcache->cooked_read (SPARC_F4_REGNUM, buf + 16);
+ regcache->cooked_read (SPARC_F5_REGNUM, buf + 20);
+ regcache->cooked_read (SPARC_F6_REGNUM, buf + 24);
+ regcache->cooked_read (SPARC_F7_REGNUM, buf + 28);
}
memcpy (valbuf, buf, len);
}
/* Integral and pointer return values. */
gdb_assert (sparc_integral_or_pointer_p (type));
- regcache_cooked_read (regcache, SPARC_O0_REGNUM, buf);
+ regcache->cooked_read (SPARC_O0_REGNUM, buf);
if (len > 4)
{
- regcache_cooked_read (regcache, SPARC_O1_REGNUM, buf + 4);
+ regcache->cooked_read (SPARC_O1_REGNUM, buf + 4);
gdb_assert (len == 8);
memcpy (valbuf, buf, 8);
}
const gdb_byte *valbuf)
{
int len = TYPE_LENGTH (type);
- gdb_byte buf[8];
+ gdb_byte buf[32];
- gdb_assert (!sparc_structure_or_union_p (type));
- gdb_assert (!(sparc_floating_p (type) && len == 16));
- gdb_assert (len <= 8);
+ gdb_assert (!sparc_structure_return_p (type));
if (sparc_floating_p (type) || sparc_complex_floating_p (type))
{
/* Floating return values. */
memcpy (buf, valbuf, len);
- regcache_cooked_write (regcache, SPARC_F0_REGNUM, buf);
+ regcache->cooked_write (SPARC_F0_REGNUM, buf);
if (len > 4)
- regcache_cooked_write (regcache, SPARC_F1_REGNUM, buf + 4);
+ regcache->cooked_write (SPARC_F1_REGNUM, buf + 4);
if (len > 8)
{
- regcache_cooked_write (regcache, SPARC_F2_REGNUM, buf + 8);
- regcache_cooked_write (regcache, SPARC_F3_REGNUM, buf + 12);
+ regcache->cooked_write (SPARC_F2_REGNUM, buf + 8);
+ regcache->cooked_write (SPARC_F3_REGNUM, buf + 12);
}
if (len > 16)
{
- regcache_cooked_write (regcache, SPARC_F4_REGNUM, buf + 16);
- regcache_cooked_write (regcache, SPARC_F5_REGNUM, buf + 20);
- regcache_cooked_write (regcache, SPARC_F6_REGNUM, buf + 24);
- regcache_cooked_write (regcache, SPARC_F7_REGNUM, buf + 28);
+ regcache->cooked_write (SPARC_F4_REGNUM, buf + 16);
+ regcache->cooked_write (SPARC_F5_REGNUM, buf + 20);
+ regcache->cooked_write (SPARC_F6_REGNUM, buf + 24);
+ regcache->cooked_write (SPARC_F7_REGNUM, buf + 28);
}
}
else
{
gdb_assert (len == 8);
memcpy (buf, valbuf, 8);
- regcache_cooked_write (regcache, SPARC_O1_REGNUM, buf + 4);
+ regcache->cooked_write (SPARC_O1_REGNUM, buf + 4);
}
else
{
/* ??? Do we need to do any sign-extension here? */
memcpy (buf + 4 - len, valbuf, len);
}
- regcache_cooked_write (regcache, SPARC_O0_REGNUM, buf);
+ regcache->cooked_write (SPARC_O0_REGNUM, buf);
}
}
guarantees that we can always find the return value, not just
before the function returns. */
- if (sparc_structure_or_union_p (type)
- || (sparc_floating_p (type) && TYPE_LENGTH (type) == 16))
+ if (sparc_structure_return_p (type))
{
ULONGEST sp;
CORE_ADDR addr;
}
}
+/* Implement the execute_dwarf_cfa_vendor_op method. */
+
+static bool
+sparc_execute_dwarf_cfa_vendor_op (struct gdbarch *gdbarch, gdb_byte op,
+ struct dwarf2_frame_state *fs)
+{
+ /* Only DW_CFA_GNU_window_save is expected on SPARC. */
+ if (op != DW_CFA_GNU_window_save)
+ return false;
+
+ uint64_t reg;
+ int size = register_size (gdbarch, 0);
+
+ fs->regs.alloc_regs (32);
+ for (reg = 8; reg < 16; reg++)
+ {
+ fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAVED_REG;
+ fs->regs.reg[reg].loc.reg = reg + 16;
+ }
+ for (reg = 16; reg < 32; reg++)
+ {
+ fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAVED_OFFSET;
+ fs->regs.reg[reg].loc.offset = (reg - 16) * size;
+ }
+
+ return true;
+}
+
\f
/* The SPARC Architecture doesn't have hardware single-step support,
and most operating systems don't implement it either, so we provide
software single-step mechanism. */
static CORE_ADDR
-sparc_analyze_control_transfer (struct frame_info *frame,
+sparc_analyze_control_transfer (struct regcache *regcache,
CORE_ADDR pc, CORE_ADDR *npc)
{
unsigned long insn = sparc_fetch_instruction (pc);
else if (X_OP (insn) == 0 && X_OP2 (insn) == 5)
{
/* Branch on Floating-Point Condition Codes with Prediction
- (FBPfcc). */
+ (FBPfcc). */
branch_p = 1;
offset = 4 * X_DISP19 (insn);
}
}
else if (X_OP (insn) == 2 && X_OP3 (insn) == 0x3a)
{
+ struct frame_info *frame = get_current_frame ();
+
/* Trap instruction (TRAP). */
- return gdbarch_tdep (get_frame_arch (frame))->step_trap (frame, insn);
+ gdbarch *arch = regcache->arch ();
+ sparc_gdbarch_tdep *tdep = (sparc_gdbarch_tdep *) gdbarch_tdep (arch);
+ return tdep->step_trap (frame, insn);
}
/* FIXME: Handle DONE and RETRY instructions. */
if (fused_p)
{
/* Fused compare-and-branch instructions are non-delayed,
- and do not have an annuling capability. So we need to
+ and do not have an annulling capability. So we need to
always set a breakpoint on both the NPC and the branch
target address. */
gdb_assert (offset != 0);
return 0;
}
-int
-sparc_software_single_step (struct frame_info *frame)
+static std::vector<CORE_ADDR>
+sparc_software_single_step (struct regcache *regcache)
{
- struct gdbarch *arch = get_frame_arch (frame);
- struct gdbarch_tdep *tdep = gdbarch_tdep (arch);
- struct address_space *aspace = get_frame_address_space (frame);
+ struct gdbarch *arch = regcache->arch ();
+ sparc_gdbarch_tdep *tdep = (sparc_gdbarch_tdep *) gdbarch_tdep (arch);
CORE_ADDR npc, nnpc;
CORE_ADDR pc, orig_npc;
+ std::vector<CORE_ADDR> next_pcs;
- pc = get_frame_register_unsigned (frame, tdep->pc_regnum);
- orig_npc = npc = get_frame_register_unsigned (frame, tdep->npc_regnum);
+ pc = regcache_raw_get_unsigned (regcache, tdep->pc_regnum);
+ orig_npc = npc = regcache_raw_get_unsigned (regcache, tdep->npc_regnum);
/* Analyze the instruction at PC. */
- nnpc = sparc_analyze_control_transfer (frame, pc, &npc);
+ nnpc = sparc_analyze_control_transfer (regcache, pc, &npc);
if (npc != 0)
- insert_single_step_breakpoint (arch, aspace, npc);
+ next_pcs.push_back (npc);
if (nnpc != 0)
- insert_single_step_breakpoint (arch, aspace, nnpc);
+ next_pcs.push_back (nnpc);
/* Assert that we have set at least one breakpoint, and that
they're not set at the same spot - unless we're going
gdb_assert (npc != 0 || nnpc != 0 || orig_npc == 0);
gdb_assert (nnpc != npc || orig_npc == 0);
- return 1;
+ return next_pcs;
}
static void
sparc_write_pc (struct regcache *regcache, CORE_ADDR pc)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
+ gdbarch *arch = regcache->arch ();
+ sparc_gdbarch_tdep *tdep = (sparc_gdbarch_tdep *) gdbarch_tdep (arch);
regcache_cooked_write_unsigned (regcache, tdep->pc_regnum, pc);
regcache_cooked_write_unsigned (regcache, tdep->npc_regnum, pc + 4);
}
\f
-/* Return the appropriate register set for the core section identified
- by SECT_NAME and SECT_SIZE. */
+/* Iterate over core file register note sections. */
-static const struct regset *
-sparc_regset_from_core_section (struct gdbarch *gdbarch,
- const char *sect_name, size_t sect_size)
+static void
+sparc_iterate_over_regset_sections (struct gdbarch *gdbarch,
+ iterate_over_regset_sections_cb *cb,
+ void *cb_data,
+ const struct regcache *regcache)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ sparc_gdbarch_tdep *tdep = (sparc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
- if (strcmp (sect_name, ".reg") == 0 && sect_size >= tdep->sizeof_gregset)
- return tdep->gregset;
+ cb (".reg", tdep->sizeof_gregset, tdep->sizeof_gregset, tdep->gregset, NULL,
+ cb_data);
+ cb (".reg2", tdep->sizeof_fpregset, tdep->sizeof_fpregset, tdep->fpregset,
+ NULL, cb_data);
+}
+\f
- if (strcmp (sect_name, ".reg2") == 0 && sect_size >= tdep->sizeof_fpregset)
- return tdep->fpregset;
+static int
+validate_tdesc_registers (const struct target_desc *tdesc,
+ struct tdesc_arch_data *tdesc_data,
+ const char *feature_name,
+ const char * const register_names[],
+ unsigned int registers_num,
+ unsigned int reg_start)
+{
+ int valid_p = 1;
+ const struct tdesc_feature *feature;
- return NULL;
+ feature = tdesc_find_feature (tdesc, feature_name);
+ if (feature == NULL)
+ return 0;
+
+ for (unsigned int i = 0; i < registers_num; i++)
+ valid_p &= tdesc_numbered_register (feature, tdesc_data,
+ reg_start + i,
+ register_names[i]);
+
+ return valid_p;
}
-\f
static struct gdbarch *
sparc32_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
{
- struct gdbarch_tdep *tdep;
+ const struct target_desc *tdesc = info.target_desc;
struct gdbarch *gdbarch;
+ int valid_p = 1;
/* If there is already a candidate, use it. */
arches = gdbarch_list_lookup_by_info (arches, &info);
return arches->gdbarch;
/* Allocate space for the new architecture. */
- tdep = XCNEW (struct gdbarch_tdep);
+ sparc_gdbarch_tdep *tdep = new sparc_gdbarch_tdep;
gdbarch = gdbarch_alloc (&info, tdep);
tdep->pc_regnum = SPARC32_PC_REGNUM;
tdep->npc_regnum = SPARC32_NPC_REGNUM;
tdep->step_trap = sparc_step_trap;
+ tdep->fpu_register_names = sparc32_fpu_register_names;
+ tdep->fpu_registers_num = ARRAY_SIZE (sparc32_fpu_register_names);
+ tdep->cp0_register_names = sparc32_cp0_register_names;
+ tdep->cp0_registers_num = ARRAY_SIZE (sparc32_cp0_register_names);
set_gdbarch_long_double_bit (gdbarch, 128);
set_gdbarch_long_double_format (gdbarch, floatformats_sparc_quad);
+ set_gdbarch_wchar_bit (gdbarch, 16);
+ set_gdbarch_wchar_signed (gdbarch, 1);
+
set_gdbarch_num_regs (gdbarch, SPARC32_NUM_REGS);
set_gdbarch_register_name (gdbarch, sparc32_register_name);
set_gdbarch_register_type (gdbarch, sparc32_register_type);
set_gdbarch_num_pseudo_regs (gdbarch, SPARC32_NUM_PSEUDO_REGS);
+ set_tdesc_pseudo_register_name (gdbarch, sparc32_pseudo_register_name);
+ set_tdesc_pseudo_register_type (gdbarch, sparc32_pseudo_register_type);
set_gdbarch_pseudo_register_read (gdbarch, sparc32_pseudo_register_read);
set_gdbarch_pseudo_register_write (gdbarch, sparc32_pseudo_register_write);
/* Stack grows downward. */
set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
- set_gdbarch_breakpoint_from_pc (gdbarch, sparc_breakpoint_from_pc);
+ set_gdbarch_breakpoint_kind_from_pc (gdbarch,
+ sparc_breakpoint::kind_from_pc);
+ set_gdbarch_sw_breakpoint_from_kind (gdbarch,
+ sparc_breakpoint::bp_from_kind);
set_gdbarch_frame_args_skip (gdbarch, 8);
- set_gdbarch_print_insn (gdbarch, print_insn_sparc);
-
set_gdbarch_software_single_step (gdbarch, sparc_software_single_step);
set_gdbarch_write_pc (gdbarch, sparc_write_pc);
set_gdbarch_dummy_id (gdbarch, sparc_dummy_id);
- set_gdbarch_unwind_pc (gdbarch, sparc_unwind_pc);
-
frame_base_set_default (gdbarch, &sparc32_frame_base);
/* Hook in the DWARF CFI frame unwinder. */
dwarf2_frame_set_init_reg (gdbarch, sparc32_dwarf2_frame_init_reg);
+ /* Register DWARF vendor CFI handler. */
+ set_gdbarch_execute_dwarf_cfa_vendor_op (gdbarch,
+ sparc_execute_dwarf_cfa_vendor_op);
/* FIXME: kettenis/20050423: Don't enable the unwinder until the
StackGhost issues have been resolved. */
frame_unwind_append_unwinder (gdbarch, &sparc32_frame_unwind);
+ if (tdesc_has_registers (tdesc))
+ {
+ tdesc_arch_data_up tdesc_data = tdesc_data_alloc ();
+
+ /* Validate that the descriptor provides the mandatory registers
+ and allocate their numbers. */
+ valid_p &= validate_tdesc_registers (tdesc, tdesc_data.get (),
+ "org.gnu.gdb.sparc.cpu",
+ sparc_core_register_names,
+ ARRAY_SIZE (sparc_core_register_names),
+ SPARC_G0_REGNUM);
+ valid_p &= validate_tdesc_registers (tdesc, tdesc_data.get (),
+ "org.gnu.gdb.sparc.fpu",
+ tdep->fpu_register_names,
+ tdep->fpu_registers_num,
+ SPARC_F0_REGNUM);
+ valid_p &= validate_tdesc_registers (tdesc, tdesc_data.get (),
+ "org.gnu.gdb.sparc.cp0",
+ tdep->cp0_register_names,
+ tdep->cp0_registers_num,
+ SPARC_F0_REGNUM
+ + tdep->fpu_registers_num);
+ if (!valid_p)
+ return NULL;
+
+ /* Target description may have changed. */
+ info.tdesc_data = tdesc_data.get ();
+ tdesc_use_registers (gdbarch, tdesc, std::move (tdesc_data));
+ }
+
/* If we have register sets, enable the generic core file support. */
if (tdep->gregset)
- set_gdbarch_regset_from_core_section (gdbarch,
- sparc_regset_from_core_section);
+ set_gdbarch_iterate_over_regset_sections
+ (gdbarch, sparc_iterate_over_regset_sections);
register_sparc_ravenscar_ops (gdbarch);
void
sparc_supply_rwindow (struct regcache *regcache, CORE_ADDR sp, int regnum)
{
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ struct gdbarch *gdbarch = regcache->arch ();
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
int offset = 0;
gdb_byte buf[8];
int i;
+ /* This function calls functions that depend on the global current thread. */
+ gdb_assert (regcache->ptid () == inferior_ptid);
+
if (sp & 1)
{
/* Registers are 64-bit. */
i7 ^ wcookie);
}
- regcache_raw_supply (regcache, i, buf);
+ regcache->raw_supply (i, buf);
}
}
}
/* Clear out the top half of the temporary buffer, and put the
register value in the bottom half if we're in 64-bit mode. */
- if (gdbarch_ptr_bit (get_regcache_arch (regcache)) == 64)
+ if (gdbarch_ptr_bit (regcache->arch ()) == 64)
{
memset (buf, 0, 4);
offset = 4;
i7 ^ wcookie);
}
- regcache_raw_supply (regcache, i, buf);
+ regcache->raw_supply (i, buf);
}
}
}
sparc_collect_rwindow (const struct regcache *regcache,
CORE_ADDR sp, int regnum)
{
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ struct gdbarch *gdbarch = regcache->arch ();
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
int offset = 0;
gdb_byte buf[8];
int i;
+ /* This function calls functions that depend on the global current thread. */
+ gdb_assert (regcache->ptid () == inferior_ptid);
+
if (sp & 1)
{
/* Registers are 64-bit. */
{
if (regnum == -1 || regnum == SPARC_SP_REGNUM || regnum == i)
{
- regcache_raw_collect (regcache, i, buf);
+ regcache->raw_collect (i, buf);
/* Handle StackGhost. */
if (i == SPARC_I7_REGNUM)
sp &= 0xffffffffUL;
/* Only use the bottom half if we're in 64-bit mode. */
- if (gdbarch_ptr_bit (get_regcache_arch (regcache)) == 64)
+ if (gdbarch_ptr_bit (regcache->arch ()) == 64)
offset = 4;
for (i = SPARC_L0_REGNUM; i <= SPARC_I7_REGNUM; i++)
{
if (regnum == -1 || regnum == SPARC_SP_REGNUM || regnum == i)
{
- regcache_raw_collect (regcache, i, buf);
+ regcache->raw_collect (i, buf);
/* Handle StackGhost. */
if (i == SPARC_I7_REGNUM)
/* Helper functions for dealing with register sets. */
void
-sparc32_supply_gregset (const struct sparc_gregset *gregset,
+sparc32_supply_gregset (const struct sparc_gregmap *gregmap,
struct regcache *regcache,
int regnum, const void *gregs)
{
- const gdb_byte *regs = gregs;
+ const gdb_byte *regs = (const gdb_byte *) gregs;
gdb_byte zero[4] = { 0 };
int i;
if (regnum == SPARC32_PSR_REGNUM || regnum == -1)
- regcache_raw_supply (regcache, SPARC32_PSR_REGNUM,
- regs + gregset->r_psr_offset);
+ regcache->raw_supply (SPARC32_PSR_REGNUM, regs + gregmap->r_psr_offset);
if (regnum == SPARC32_PC_REGNUM || regnum == -1)
- regcache_raw_supply (regcache, SPARC32_PC_REGNUM,
- regs + gregset->r_pc_offset);
+ regcache->raw_supply (SPARC32_PC_REGNUM, regs + gregmap->r_pc_offset);
if (regnum == SPARC32_NPC_REGNUM || regnum == -1)
- regcache_raw_supply (regcache, SPARC32_NPC_REGNUM,
- regs + gregset->r_npc_offset);
+ regcache->raw_supply (SPARC32_NPC_REGNUM, regs + gregmap->r_npc_offset);
if (regnum == SPARC32_Y_REGNUM || regnum == -1)
- regcache_raw_supply (regcache, SPARC32_Y_REGNUM,
- regs + gregset->r_y_offset);
+ regcache->raw_supply (SPARC32_Y_REGNUM, regs + gregmap->r_y_offset);
if (regnum == SPARC_G0_REGNUM || regnum == -1)
- regcache_raw_supply (regcache, SPARC_G0_REGNUM, &zero);
+ regcache->raw_supply (SPARC_G0_REGNUM, &zero);
if ((regnum >= SPARC_G1_REGNUM && regnum <= SPARC_O7_REGNUM) || regnum == -1)
{
- int offset = gregset->r_g1_offset;
+ int offset = gregmap->r_g1_offset;
for (i = SPARC_G1_REGNUM; i <= SPARC_O7_REGNUM; i++)
{
if (regnum == i || regnum == -1)
- regcache_raw_supply (regcache, i, regs + offset);
+ regcache->raw_supply (i, regs + offset);
offset += 4;
}
}
if ((regnum >= SPARC_L0_REGNUM && regnum <= SPARC_I7_REGNUM) || regnum == -1)
{
/* Not all of the register set variants include Locals and
- Inputs. For those that don't, we read them off the stack. */
- if (gregset->r_l0_offset == -1)
+ Inputs. For those that don't, we read them off the stack. */
+ if (gregmap->r_l0_offset == -1)
{
ULONGEST sp;
}
else
{
- int offset = gregset->r_l0_offset;
+ int offset = gregmap->r_l0_offset;
for (i = SPARC_L0_REGNUM; i <= SPARC_I7_REGNUM; i++)
{
if (regnum == i || regnum == -1)
- regcache_raw_supply (regcache, i, regs + offset);
+ regcache->raw_supply (i, regs + offset);
offset += 4;
}
}
}
void
-sparc32_collect_gregset (const struct sparc_gregset *gregset,
+sparc32_collect_gregset (const struct sparc_gregmap *gregmap,
const struct regcache *regcache,
int regnum, void *gregs)
{
- gdb_byte *regs = gregs;
+ gdb_byte *regs = (gdb_byte *) gregs;
int i;
if (regnum == SPARC32_PSR_REGNUM || regnum == -1)
- regcache_raw_collect (regcache, SPARC32_PSR_REGNUM,
- regs + gregset->r_psr_offset);
+ regcache->raw_collect (SPARC32_PSR_REGNUM, regs + gregmap->r_psr_offset);
if (regnum == SPARC32_PC_REGNUM || regnum == -1)
- regcache_raw_collect (regcache, SPARC32_PC_REGNUM,
- regs + gregset->r_pc_offset);
+ regcache->raw_collect (SPARC32_PC_REGNUM, regs + gregmap->r_pc_offset);
if (regnum == SPARC32_NPC_REGNUM || regnum == -1)
- regcache_raw_collect (regcache, SPARC32_NPC_REGNUM,
- regs + gregset->r_npc_offset);
+ regcache->raw_collect (SPARC32_NPC_REGNUM, regs + gregmap->r_npc_offset);
if (regnum == SPARC32_Y_REGNUM || regnum == -1)
- regcache_raw_collect (regcache, SPARC32_Y_REGNUM,
- regs + gregset->r_y_offset);
+ regcache->raw_collect (SPARC32_Y_REGNUM, regs + gregmap->r_y_offset);
if ((regnum >= SPARC_G1_REGNUM && regnum <= SPARC_O7_REGNUM) || regnum == -1)
{
- int offset = gregset->r_g1_offset;
+ int offset = gregmap->r_g1_offset;
/* %g0 is always zero. */
for (i = SPARC_G1_REGNUM; i <= SPARC_O7_REGNUM; i++)
{
if (regnum == i || regnum == -1)
- regcache_raw_collect (regcache, i, regs + offset);
+ regcache->raw_collect (i, regs + offset);
offset += 4;
}
}
if ((regnum >= SPARC_L0_REGNUM && regnum <= SPARC_I7_REGNUM) || regnum == -1)
{
/* Not all of the register set variants include Locals and
- Inputs. For those that don't, we read them off the stack. */
- if (gregset->r_l0_offset != -1)
+ Inputs. For those that don't, we read them off the stack. */
+ if (gregmap->r_l0_offset != -1)
{
- int offset = gregset->r_l0_offset;
+ int offset = gregmap->r_l0_offset;
for (i = SPARC_L0_REGNUM; i <= SPARC_I7_REGNUM; i++)
{
if (regnum == i || regnum == -1)
- regcache_raw_collect (regcache, i, regs + offset);
+ regcache->raw_collect (i, regs + offset);
offset += 4;
}
}
}
void
-sparc32_supply_fpregset (const struct sparc_fpregset *fpregset,
+sparc32_supply_fpregset (const struct sparc_fpregmap *fpregmap,
struct regcache *regcache,
int regnum, const void *fpregs)
{
- const gdb_byte *regs = fpregs;
+ const gdb_byte *regs = (const gdb_byte *) fpregs;
int i;
for (i = 0; i < 32; i++)
{
if (regnum == (SPARC_F0_REGNUM + i) || regnum == -1)
- regcache_raw_supply (regcache, SPARC_F0_REGNUM + i,
- regs + fpregset->r_f0_offset + (i * 4));
+ regcache->raw_supply (SPARC_F0_REGNUM + i,
+ regs + fpregmap->r_f0_offset + (i * 4));
}
if (regnum == SPARC32_FSR_REGNUM || regnum == -1)
- regcache_raw_supply (regcache, SPARC32_FSR_REGNUM,
- regs + fpregset->r_fsr_offset);
+ regcache->raw_supply (SPARC32_FSR_REGNUM, regs + fpregmap->r_fsr_offset);
}
void
-sparc32_collect_fpregset (const struct sparc_fpregset *fpregset,
+sparc32_collect_fpregset (const struct sparc_fpregmap *fpregmap,
const struct regcache *regcache,
int regnum, void *fpregs)
{
- gdb_byte *regs = fpregs;
+ gdb_byte *regs = (gdb_byte *) fpregs;
int i;
for (i = 0; i < 32; i++)
{
if (regnum == (SPARC_F0_REGNUM + i) || regnum == -1)
- regcache_raw_collect (regcache, SPARC_F0_REGNUM + i,
- regs + fpregset->r_f0_offset + (i * 4));
+ regcache->raw_collect (SPARC_F0_REGNUM + i,
+ regs + fpregmap->r_f0_offset + (i * 4));
}
if (regnum == SPARC32_FSR_REGNUM || regnum == -1)
- regcache_raw_collect (regcache, SPARC32_FSR_REGNUM,
- regs + fpregset->r_fsr_offset);
+ regcache->raw_collect (SPARC32_FSR_REGNUM,
+ regs + fpregmap->r_fsr_offset);
}
\f
/* SunOS 4. */
/* From <machine/reg.h>. */
-const struct sparc_gregset sparc32_sunos4_gregset =
+const struct sparc_gregmap sparc32_sunos4_gregmap =
{
0 * 4, /* %psr */
1 * 4, /* %pc */
-1 /* %l0 */
};
-const struct sparc_fpregset sparc32_sunos4_fpregset =
+const struct sparc_fpregmap sparc32_sunos4_fpregmap =
{
0 * 4, /* %f0 */
33 * 4, /* %fsr */
};
-const struct sparc_fpregset sparc32_bsd_fpregset =
+const struct sparc_fpregmap sparc32_bsd_fpregmap =
{
0 * 4, /* %f0 */
32 * 4, /* %fsr */
};
-\f
-
-/* Provide a prototype to silence -Wmissing-prototypes. */
-void _initialize_sparc_tdep (void);
+void _initialize_sparc_tdep ();
void
-_initialize_sparc_tdep (void)
+_initialize_sparc_tdep ()
{
register_gdbarch_init (bfd_arch_sparc, sparc32_gdbarch_init);
}