/* Target-dependent code for the NEC V850 for GDB, the GNU debugger.
- Copyright (C) 1996-2015 Free Software Foundation, Inc.
+ Copyright (C) 1996-2022 Free Software Foundation, Inc.
This file is part of GDB.
#include "frame-base.h"
#include "trad-frame.h"
#include "frame-unwind.h"
-#include "dwarf2-frame.h"
+#include "dwarf2/frame.h"
#include "gdbtypes.h"
#include "inferior.h"
#include "gdbcore.h"
#include "osabi.h"
#include "elf-bfd.h"
#include "elf/v850.h"
+#include "gdbarch.h"
enum
{
/* Architecture specific data. */
-struct gdbarch_tdep
+struct v850_gdbarch_tdep : gdbarch_tdep
{
/* Fields from the ELF header. */
- int e_flags;
- int e_machine;
+ int e_flags = 0;
+ int e_machine = 0;
/* Which ABI are we using? */
- enum v850_abi abi;
- int eight_byte_align;
+ enum v850_abi abi {};
+ int eight_byte_align = 0;
};
struct v850_frame_cache
int uses_fp;
/* Saved registers. */
- struct trad_frame_saved_reg *saved_regs;
+ trad_frame_saved_reg *saved_regs;
};
/* Info gleaned from scanning a function's prologue. */
static int
v850_type_is_scalar (struct type *t)
{
- return (TYPE_CODE (t) != TYPE_CODE_STRUCT
- && TYPE_CODE (t) != TYPE_CODE_UNION
- && TYPE_CODE (t) != TYPE_CODE_ARRAY);
+ return (t->code () != TYPE_CODE_STRUCT
+ && t->code () != TYPE_CODE_UNION
+ && t->code () != TYPE_CODE_ARRAY);
}
/* Should call_function allocate stack space for a struct return? */
{
int i;
struct type *fld_type, *tgt_type;
+ v850_gdbarch_tdep *tdep = (v850_gdbarch_tdep *) gdbarch_tdep (gdbarch);
- if (gdbarch_tdep (gdbarch)->abi == V850_ABI_RH850)
+ if (tdep->abi == V850_ABI_RH850)
{
if (v850_type_is_scalar (type) && TYPE_LENGTH(type) <= 8)
return 0;
/* The value is a structure or union with a single element and that
element is either a single basic type or an array of a single basic
type whose size is greater than or equal to 4 -> returned in register. */
- if ((TYPE_CODE (type) == TYPE_CODE_STRUCT
- || TYPE_CODE (type) == TYPE_CODE_UNION)
- && TYPE_NFIELDS (type) == 1)
+ if ((type->code () == TYPE_CODE_STRUCT
+ || type->code () == TYPE_CODE_UNION)
+ && type->num_fields () == 1)
{
- fld_type = TYPE_FIELD_TYPE (type, 0);
+ fld_type = type->field (0).type ();
if (v850_type_is_scalar (fld_type) && TYPE_LENGTH (fld_type) >= 4)
return 0;
- if (TYPE_CODE (fld_type) == TYPE_CODE_ARRAY)
- {
+ if (fld_type->code () == TYPE_CODE_ARRAY)
+ {
tgt_type = TYPE_TARGET_TYPE (fld_type);
if (v850_type_is_scalar (tgt_type) && TYPE_LENGTH (tgt_type) >= 4)
return 0;
/* The value is a structure whose first element is an integer or a float,
and which contains no arrays of more than two elements -> returned in
register. */
- if (TYPE_CODE (type) == TYPE_CODE_STRUCT
- && v850_type_is_scalar (TYPE_FIELD_TYPE (type, 0))
- && TYPE_LENGTH (TYPE_FIELD_TYPE (type, 0)) == 4)
+ if (type->code () == TYPE_CODE_STRUCT
+ && v850_type_is_scalar (type->field (0).type ())
+ && TYPE_LENGTH (type->field (0).type ()) == 4)
{
- for (i = 1; i < TYPE_NFIELDS (type); ++i)
- {
- fld_type = TYPE_FIELD_TYPE (type, 0);
- if (TYPE_CODE (fld_type) == TYPE_CODE_ARRAY)
+ for (i = 1; i < type->num_fields (); ++i)
+ {
+ fld_type = type->field (0).type ();
+ if (fld_type->code () == TYPE_CODE_ARRAY)
{
tgt_type = TYPE_TARGET_TYPE (fld_type);
- if (TYPE_LENGTH (fld_type) >= 0 && TYPE_LENGTH (tgt_type) >= 0
+ if (TYPE_LENGTH (tgt_type) > 0
&& TYPE_LENGTH (fld_type) / TYPE_LENGTH (tgt_type) > 2)
return 1;
}
/* The value is a union which contains at least one field which
would be returned in registers according to these rules ->
returned in register. */
- if (TYPE_CODE (type) == TYPE_CODE_UNION)
+ if (type->code () == TYPE_CODE_UNION)
{
- for (i = 0; i < TYPE_NFIELDS (type); ++i)
- {
- fld_type = TYPE_FIELD_TYPE (type, 0);
+ for (i = 0; i < type->num_fields (); ++i)
+ {
+ fld_type = type->field (0).type ();
if (!v850_use_struct_convention (gdbarch, fld_type))
return 0;
}
}
else if ((insn & 0xffe0) == ((E_SP_REGNUM << 11) | 0x0240))
- /* add <imm>,sp */
+ /* add <imm>,sp */
pi->sp_offset += ((insn & 0x1f) ^ 0x10) - 0x10;
else if (insn == ((E_SP_REGNUM << 11) | 0x0600 | E_SP_REGNUM))
- /* addi <imm>,sp,sp */
+ /* addi <imm>,sp,sp */
pi->sp_offset += insn2;
else if (insn == ((E_FP_REGNUM << 11) | 0x0000 | E_SP_REGNUM))
- /* mov sp,fp */
+ /* mov sp,fp */
pi->uses_fp = 1;
else if (insn == ((E_R12_REGNUM << 11) | 0x0640 | E_R0_REGNUM))
- /* movhi hi(const),r0,r12 */
+ /* movhi hi(const),r0,r12 */
r12_tmp = insn2 << 16;
else if (insn == ((E_R12_REGNUM << 11) | 0x0620 | E_R12_REGNUM))
- /* movea lo(const),r12,r12 */
+ /* movea lo(const),r12,r12 */
r12_tmp += insn2;
else if (insn == ((E_SP_REGNUM << 11) | 0x01c0 | E_R12_REGNUM) && r12_tmp)
- /* add r12,sp */
+ /* add r12,sp */
pi->sp_offset += r12_tmp;
else if (insn == ((E_EP_REGNUM << 11) | 0x0000 | E_SP_REGNUM))
- /* mov sp,ep */
+ /* mov sp,ep */
ep_used = 1;
else if (insn == ((E_EP_REGNUM << 11) | 0x0000 | E_R1_REGNUM))
- /* mov r1,ep */
+ /* mov r1,ep */
ep_used = 0;
else if (((insn & 0x07ff) == (0x0760 | E_SP_REGNUM)
|| (pi->uses_fp
for (pifsr_tmp = pifsrs; pifsr_tmp != pifsr; pifsr_tmp++)
{
pifsr_tmp->offset -= pi->sp_offset - pifsr_tmp->cur_frameoffset;
- pi->saved_regs[pifsr_tmp->reg].addr = pifsr_tmp->offset;
+ pi->saved_regs[pifsr_tmp->reg].set_addr (pifsr_tmp->offset);
}
return current_pc;
{
int i;
- for (i = 0; i < TYPE_NFIELDS (type); i++)
+ for (i = 0; i < type->num_fields (); i++)
{
- if (v850_eight_byte_align_p (TYPE_FIELD_TYPE (type, i)))
+ if (v850_eight_byte_align_p (type->field (i).type ()))
return 1;
}
}
int nargs,
struct value **args,
CORE_ADDR sp,
- int struct_return,
+ function_call_return_method return_method,
CORE_ADDR struct_addr)
{
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
int argreg;
int argnum;
- int len = 0;
+ int arg_space = 0;
int stack_offset;
+ v850_gdbarch_tdep *tdep = (v850_gdbarch_tdep *) gdbarch_tdep (gdbarch);
- if (gdbarch_tdep (gdbarch)->abi == V850_ABI_RH850)
+ if (tdep->abi == V850_ABI_RH850)
stack_offset = 0;
else
- /* The offset onto the stack at which we will start copying parameters
- (after the registers are used up) begins at 16 rather than at zero.
- That's how the ABI is defined, though there's no indication that these
- 16 bytes are used for anything, not even for saving incoming
- argument registers. */
- stack_offset = 16;
+ {
+ /* The offset onto the stack at which we will start copying parameters
+ (after the registers are used up) begins at 16 rather than at zero.
+ That's how the ABI is defined, though there's no indication that these
+ 16 bytes are used for anything, not even for saving incoming
+ argument registers. */
+ stack_offset = 16;
+ }
/* Now make space on the stack for the args. */
for (argnum = 0; argnum < nargs; argnum++)
- len += ((TYPE_LENGTH (value_type (args[argnum])) + 3) & ~3);
- sp -= len + stack_offset;
+ arg_space += ((TYPE_LENGTH (value_type (args[argnum])) + 3) & ~3);
+ sp -= arg_space + stack_offset;
argreg = E_ARG0_REGNUM;
/* The struct_return pointer occupies the first parameter register. */
- if (struct_return)
+ if (return_method == return_method_struct)
regcache_cooked_write_unsigned (regcache, argreg++, struct_addr);
/* Now load as many as possible of the first arguments into
gdb_byte valbuf[v850_reg_size];
if (!v850_type_is_scalar (value_type (*args))
- && gdbarch_tdep (gdbarch)->abi == V850_ABI_GCC
+ && tdep->abi == V850_ABI_GCC
&& TYPE_LENGTH (value_type (*args)) > E_MAX_RETTYPE_SIZE_IN_REGS)
{
store_unsigned_integer (valbuf, 4, byte_order,
else
{
len = TYPE_LENGTH (value_type (*args));
- val = (gdb_byte *) value_contents (*args);
+ val = (gdb_byte *) value_contents (*args).data ();
}
- if (gdbarch_tdep (gdbarch)->eight_byte_align
- && v850_eight_byte_align_p (value_type (*args)))
- {
+ if (tdep->eight_byte_align
+ && v850_eight_byte_align_p (value_type (*args)))
+ {
if (argreg <= E_ARGLAST_REGNUM && (argreg & 1))
argreg++;
else if (stack_offset & 0x4)
v850_extract_return_value (struct type *type, struct regcache *regcache,
gdb_byte *valbuf)
{
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ struct gdbarch *gdbarch = regcache->arch ();
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
int len = TYPE_LENGTH (type);
gdb_byte buf[v850_reg_size];
for (i = 0; len > 0; i += 4, len -= 4)
{
- regcache_raw_read (regcache, regnum++, buf);
+ regcache->raw_read (regnum++, buf);
memcpy (valbuf + i, buf, len > 4 ? 4 : len);
}
}
v850_store_return_value (struct type *type, struct regcache *regcache,
const gdb_byte *valbuf)
{
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ struct gdbarch *gdbarch = regcache->arch ();
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
int len = TYPE_LENGTH (type);
{
int i, regnum = E_V0_REGNUM;
for (i = 0; i < len; i += 4)
- regcache_raw_write (regcache, regnum++, valbuf + i);
+ regcache->raw_write (regnum++, valbuf + i);
}
}
return RETURN_VALUE_REGISTER_CONVENTION;
}
-static const unsigned char *
-v850_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr,
- int *lenptr)
-{
- static unsigned char breakpoint[] = { 0x85, 0x05 };
+/* Implement the breakpoint_kind_from_pc gdbarch method. */
- *lenptr = sizeof (breakpoint);
- return breakpoint;
+static int
+v850_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr)
+{
+ return 2;
}
-/* Implement software breakpoints by using the dbtrap instruction.
- Older architectures had no such instruction. For those, an
- unconditional branch to self instruction is used. */
+/* Implement the sw_breakpoint_from_kind gdbarch method. */
-static const unsigned char *
-v850_dbtrap_breakpoint_from_pc (struct gdbarch *gdbarch,
- CORE_ADDR *pcptr, int *lenptr)
+static const gdb_byte *
+v850_sw_breakpoint_from_kind (struct gdbarch *gdbarch, int kind, int *size)
{
- static unsigned char breakpoint[] = { 0x40, 0xf8 };
+ *size = kind;
+
+ switch (gdbarch_bfd_arch_info (gdbarch)->mach)
+ {
+ case bfd_mach_v850e2:
+ case bfd_mach_v850e2v3:
+ case bfd_mach_v850e3v5:
+ {
+ /* Implement software breakpoints by using the dbtrap instruction.
+ Older architectures had no such instruction. For those, an
+ unconditional branch to self instruction is used. */
- *lenptr = sizeof (breakpoint);
- return breakpoint;
+ static unsigned char dbtrap_breakpoint[] = { 0x40, 0xf8 };
+
+ return dbtrap_breakpoint;
+ }
+ break;
+ default:
+ {
+ static unsigned char breakpoint[] = { 0x85, 0x05 };
+
+ return breakpoint;
+ }
+ break;
+ }
}
static struct v850_frame_cache *
int i;
if (*this_cache)
- return *this_cache;
+ return (struct v850_frame_cache *) *this_cache;
cache = v850_alloc_frame_cache (this_frame);
*this_cache = cache;
if (!cache->uses_fp)
{
/* We didn't find a valid frame, which means that CACHE->base
- currently holds the frame pointer for our calling frame. If
- we're at the start of a function, or somewhere half-way its
- prologue, the function's frame probably hasn't been fully
- setup yet. Try to reconstruct the base address for the stack
- frame by looking at the stack pointer. For truly "frameless"
- functions this might work too. */
+ currently holds the frame pointer for our calling frame. If
+ we're at the start of a function, or somewhere half-way its
+ prologue, the function's frame probably hasn't been fully
+ setup yet. Try to reconstruct the base address for the stack
+ frame by looking at the stack pointer. For truly "frameless"
+ functions this might work too. */
cache->base = get_frame_register_unsigned (this_frame, E_SP_REGNUM);
}
/* Now that we have the base address for the stack frame we can
calculate the value of sp in the calling frame. */
- trad_frame_set_value (cache->saved_regs, E_SP_REGNUM,
- cache->base - cache->sp_offset);
+ cache->saved_regs[E_SP_REGNUM].set_value (cache->base - cache->sp_offset);
/* Adjust all the saved registers such that they contain addresses
instead of offsets. */
for (i = 0; i < gdbarch_num_regs (gdbarch); i++)
- if (trad_frame_addr_p (cache->saved_regs, i))
- cache->saved_regs[i].addr += cache->base;
+ if (cache->saved_regs[i].is_addr ())
+ cache->saved_regs[i].set_addr (cache->saved_regs[i].addr ()
+ + cache->base);
/* The call instruction moves the caller's PC in the callee's LP.
Since this is an unwind, do the reverse. Copy the location of LP
if (cache->base == 0)
return;
- *this_id = frame_id_build (cache->saved_regs[E_SP_REGNUM].addr, cache->pc);
+ *this_id = frame_id_build (cache->saved_regs[E_SP_REGNUM].addr (), cache->pc);
}
static const struct frame_unwind v850_frame_unwind = {
+ "v850 prologue",
NORMAL_FRAME,
default_frame_unwind_stop_reason,
v850_frame_this_id,
default_frame_sniffer
};
-static CORE_ADDR
-v850_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
-{
- return frame_unwind_register_unsigned (next_frame,
- gdbarch_sp_regnum (gdbarch));
-}
-
-static CORE_ADDR
-v850_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
-{
- return frame_unwind_register_unsigned (next_frame,
- gdbarch_pc_regnum (gdbarch));
-}
-
-static struct frame_id
-v850_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
-{
- CORE_ADDR sp = get_frame_register_unsigned (this_frame,
- gdbarch_sp_regnum (gdbarch));
- return frame_id_build (sp, get_frame_pc (this_frame));
-}
-
static CORE_ADDR
v850_frame_base_address (struct frame_info *this_frame, void **this_cache)
{
v850_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
{
struct gdbarch *gdbarch;
- struct gdbarch_tdep *tdep;
int e_flags, e_machine;
/* Extract the elf_flags if available. */
arches != NULL;
arches = gdbarch_list_lookup_by_info (arches->next, &info))
{
- if (gdbarch_tdep (arches->gdbarch)->e_flags != e_flags
- || gdbarch_tdep (arches->gdbarch)->e_machine != e_machine)
+ v850_gdbarch_tdep *tdep
+ = (v850_gdbarch_tdep *) gdbarch_tdep (arches->gdbarch);
+
+ if (tdep->e_flags != e_flags || tdep->e_machine != e_machine)
continue;
return arches->gdbarch;
}
- tdep = (struct gdbarch_tdep *) xmalloc (sizeof (struct gdbarch_tdep));
+
+ v850_gdbarch_tdep *tdep = new v850_gdbarch_tdep;
tdep->e_flags = e_flags;
tdep->e_machine = e_machine;
set_gdbarch_addr_bit (gdbarch, 4 * TARGET_CHAR_BIT);
set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
- switch (info.bfd_arch_info->mach)
- {
- case bfd_mach_v850e2:
- case bfd_mach_v850e2v3:
- case bfd_mach_v850e3v5:
- set_gdbarch_breakpoint_from_pc (gdbarch, v850_dbtrap_breakpoint_from_pc);
- break;
- default:
- set_gdbarch_breakpoint_from_pc (gdbarch, v850_breakpoint_from_pc);
- break;
- }
+ set_gdbarch_breakpoint_kind_from_pc (gdbarch, v850_breakpoint_kind_from_pc);
+ set_gdbarch_sw_breakpoint_from_kind (gdbarch, v850_sw_breakpoint_from_kind);
set_gdbarch_return_value (gdbarch, v850_return_value);
set_gdbarch_push_dummy_call (gdbarch, v850_push_dummy_call);
set_gdbarch_skip_prologue (gdbarch, v850_skip_prologue);
- set_gdbarch_print_insn (gdbarch, print_insn_v850);
-
set_gdbarch_frame_align (gdbarch, v850_frame_align);
- set_gdbarch_unwind_sp (gdbarch, v850_unwind_sp);
- set_gdbarch_unwind_pc (gdbarch, v850_unwind_pc);
- set_gdbarch_dummy_id (gdbarch, v850_dummy_id);
frame_base_set_default (gdbarch, &v850_frame_base);
/* Hook in ABI-specific overrides, if they have been registered. */
return gdbarch;
}
-extern initialize_file_ftype _initialize_v850_tdep; /* -Wmissing-prototypes */
-
+void _initialize_v850_tdep ();
void
-_initialize_v850_tdep (void)
+_initialize_v850_tdep ()
{
register_gdbarch_init (bfd_arch_v850, v850_gdbarch_init);
register_gdbarch_init (bfd_arch_v850_rh850, v850_gdbarch_init);