/* Target-dependent code for SPARC.
- Copyright (C) 2003-2020 Free Software Foundation, Inc.
+ Copyright (C) 2003-2021 Free Software Foundation, Inc.
This file is part of GDB.
#include "arch-utils.h"
#include "dis-asm.h"
#include "dwarf2.h"
-#include "dwarf2-frame.h"
+#include "dwarf2/frame.h"
#include "frame.h"
#include "frame-base.h"
#include "frame-unwind.h"
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 = current_top_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:
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:
static bool
sparc_structure_return_p (const struct type *type)
{
- if (TYPE_CODE (type) == TYPE_CODE_ARRAY && TYPE_VECTOR (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))))
static bool
sparc_arg_by_memory_p (const struct type *type)
{
- if (TYPE_CODE (type) == TYPE_CODE_ARRAY && TYPE_VECTOR (type))
+ 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))))
#define SPARC32_CP0_REGISTERS \
"y", "psr", "wim", "tbr", "pc", "npc", "fsr", "csr"
-static const char *sparc_core_register_names[] = { SPARC_CORE_REGISTERS };
-static const char *sparc32_fpu_register_names[] = { SPARC32_FPU_REGISTERS };
-static const char *sparc32_cp0_register_names[] = { SPARC32_CP0_REGISTERS };
+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 *sparc32_register_names[] =
+static const char * const sparc32_register_names[] =
{
SPARC_CORE_REGISTERS,
SPARC32_FPU_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"
return sparc32_pseudo_register_names[regnum];
internal_error (__FILE__, __LINE__,
- _("sparc32_pseudo_register_name: bad register number %d"),
- regnum);
+ _("sparc32_pseudo_register_name: bad register number %d"),
+ regnum);
}
/* Return the name of register REGNUM. */
return builtin_type (gdbarch)->builtin_double;
internal_error (__FILE__, __LINE__,
- _("sparc32_pseudo_register_type: bad register number %d"),
- regnum);
+ _("sparc32_pseudo_register_type: bad register number %d"),
+ regnum);
}
/* Return the GDB type object for the "standard" data type of data in
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);
gdb_byte buf[4];
if (len < 4)
- {
- memset (buf, 0, 4 - len);
- memcpy (buf + 4 - len, valbuf, len);
- valbuf = buf;
- len = 4;
- }
+ {
+ memset (buf, 0, 4 - len);
+ memcpy (buf + 4 - len, valbuf, len);
+ valbuf = buf;
+ len = 4;
+ }
gdb_assert (len == 4 || len == 8);
/* 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;
}
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);
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)
{
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);
}
}
gdb_assert (!sparc_structure_return_p (type));
if (sparc_floating_p (type) || sparc_complex_floating_p (type)
- || TYPE_CODE (type) == TYPE_CODE_ARRAY)
+ || type->code () == TYPE_CODE_ARRAY)
{
/* Floating return values. */
regcache->cooked_read (SPARC_F0_REGNUM, buf);
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);
}
static int
validate_tdesc_registers (const struct target_desc *tdesc,
- struct tdesc_arch_data *tdesc_data,
- const char *feature_name,
- const char *register_names[],
- unsigned int registers_num,
- unsigned int reg_start)
+ 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;
for (unsigned int i = 0; i < registers_num; i++)
valid_p &= tdesc_numbered_register (feature, tdesc_data,
- reg_start + i,
- register_names[i]);
+ reg_start + i,
+ register_names[i]);
return valid_p;
}
if (tdesc_has_registers (tdesc))
{
- struct tdesc_arch_data *tdesc_data = tdesc_data_alloc ();
+ 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,
- "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,
- "org.gnu.gdb.sparc.fpu",
- tdep->fpu_register_names,
- tdep->fpu_registers_num,
- SPARC_F0_REGNUM);
- valid_p &= validate_tdesc_registers (tdesc, tdesc_data,
- "org.gnu.gdb.sparc.cp0",
- tdep->cp0_register_names,
- tdep->cp0_registers_num,
- SPARC_F0_REGNUM
- + tdep->fpu_registers_num);
+ 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)
- {
- tdesc_data_cleanup (tdesc_data);
- return NULL;
- }
+ return NULL;
/* Target description may have changed. */
- info.tdesc_data = tdesc_data;
- tdesc_use_registers (gdbarch, tdesc, tdesc_data);
+ 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. */
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. */
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 >= 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. */
+ Inputs. For those that don't, we read them off the stack. */
if (gregmap->r_l0_offset == -1)
{
ULONGEST sp;
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. */
+ Inputs. For those that don't, we read them off the stack. */
if (gregmap->r_l0_offset != -1)
{
int offset = gregmap->r_l0_offset;