/* Target-dependent code for SPARC.
- Copyright (C) 2003-2018 Free Software Foundation, Inc.
+ Copyright (C) 2003-2020 Free Software Foundation, Inc.
This file is part of GDB.
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_top_target ();
gdb_byte buf[8];
int len;
return 0;
}
-/* Check whether TYPE is returned on registers. */
+/* 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) == TYPE_CODE_ARRAY && TYPE_LENGTH (type) <= 8)
+ if (TYPE_CODE (type) == TYPE_CODE_ARRAY && TYPE_VECTOR (type))
{
- struct type *t = check_typedef (TYPE_TARGET_TYPE (type));
+ /* 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 (t) && TYPE_LENGTH (t) == 8)
- return true;
- return false;
+ 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);
}
- if (sparc_floating_p (type) && TYPE_LENGTH (type) == 16)
- return true;
+
+ /* Other than that, only aggregates of all sizes get returned by
+ memory. */
return sparc_structure_or_union_p (type);
}
-/* Check whether TYPE is passed on registers. */
+/* Return true if arguments of the given TYPE are passed by
+ memory; false if returned by register. */
static bool
-sparc_arg_on_registers_p (const struct type *type)
+sparc_arg_by_memory_p (const struct type *type)
{
- if (TYPE_CODE (type) == TYPE_CODE_ARRAY && TYPE_LENGTH (type) <= 8)
+ if (TYPE_CODE (type) == TYPE_CODE_ARRAY && TYPE_VECTOR (type))
{
- struct type *t = check_typedef (TYPE_TARGET_TYPE (type));
-
- if (sparc_floating_p (t) && TYPE_LENGTH (t) == 8)
- return false;
- return true;
+ /* 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);
}
- if (sparc_structure_or_union_p (type) || sparc_complex_floating_p (type)
- || (sparc_floating_p (type) && TYPE_LENGTH (type) == 16))
- return false;
- return true;
+
+ /* 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. */
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;
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. */
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 = regcache->arch ();
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
struct type *type = value_type (args[i]);
int len = TYPE_LENGTH (type);
- if (!sparc_arg_on_registers_p (type))
+ if (sparc_arg_by_memory_p (type))
{
/* Structure, Union and Quad-Precision Arguments. */
sp -= len;
}
else
{
- /* Integral and pointer arguments. */
- gdb_assert (sparc_integral_or_pointer_p (type)
- || (TYPE_CODE (type) == TYPE_CODE_ARRAY && len <= 8));
+ /* Arguments passed via the General Purpose Registers. */
num_elements += ((len + 3) / 4);
}
}
{
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;
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. */
|| TYPE_CODE (type) == 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);
}
{
/* 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);
}
}
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);
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
- cb (".reg", tdep->sizeof_gregset, tdep->gregset, NULL, cb_data);
- cb (".reg2", tdep->sizeof_fpregset, tdep->fpregset, NULL, cb_data);
+ 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
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. */
i7 ^ wcookie);
}
- regcache_raw_supply (regcache, i, buf);
+ regcache->raw_supply (i, buf);
}
}
}
i7 ^ wcookie);
}
- regcache_raw_supply (regcache, i, buf);
+ regcache->raw_supply (i, buf);
}
}
}
{
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)
{
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)
int i;
if (regnum == SPARC32_PSR_REGNUM || regnum == -1)
- regcache_raw_supply (regcache, SPARC32_PSR_REGNUM,
- regs + gregmap->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 + gregmap->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 + gregmap->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 + gregmap->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)
{
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;
}
}
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;
}
}
int i;
if (regnum == SPARC32_PSR_REGNUM || regnum == -1)
- regcache_raw_collect (regcache, SPARC32_PSR_REGNUM,
- regs + gregmap->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 + gregmap->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 + gregmap->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 + gregmap->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)
{
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;
}
}
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;
}
}
for (i = 0; i < 32; i++)
{
if (regnum == (SPARC_F0_REGNUM + i) || regnum == -1)
- regcache_raw_supply (regcache, SPARC_F0_REGNUM + i,
- regs + fpregmap->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 + fpregmap->r_fsr_offset);
+ regcache->raw_supply (SPARC32_FSR_REGNUM, regs + fpregmap->r_fsr_offset);
}
void
for (i = 0; i < 32; i++)
{
if (regnum == (SPARC_F0_REGNUM + i) || regnum == -1)
- regcache_raw_collect (regcache, SPARC_F0_REGNUM + i,
- regs + fpregmap->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 + fpregmap->r_fsr_offset);
+ regcache->raw_collect (SPARC32_FSR_REGNUM,
+ regs + fpregmap->r_fsr_offset);
}
\f