/* Target-dependent code for Analog Devices Blackfin processor, for GDB.
- Copyright (C) 2005-2012 Free Software Foundation, Inc.
+ Copyright (C) 2005-2020 Free Software Foundation, Inc.
Contributed by Analog Devices, Inc.
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "defs.h"
-#include "gdb_string.h"
#include "inferior.h"
#include "gdbcore.h"
#include "arch-utils.h"
#include "frame-base.h"
#include "trad-frame.h"
#include "dis-asm.h"
-#include "gdb_assert.h"
#include "sim-regno.h"
#include "gdb/sim-bfin.h"
#include "dwarf2-frame.h"
BFIN_LB1_REGNUM
};
+/* Big enough to hold the size of the largest register in bytes. */
+#define BFIN_MAX_REGISTER_SIZE 4
struct bfin_frame_cache
{
int i;
if (*this_cache)
- return *this_cache;
+ return (struct bfin_frame_cache *) *this_cache;
cache = bfin_alloc_frame_cache ();
*this_cache = cache;
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);
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
- char buf[4];
int i;
long reg_r0, reg_r1, reg_r2;
int total_len = 0;
- enum bfin_abi abi = bfin_abi (gdbarch);
- CORE_ADDR func_addr = find_function_addr (function, NULL);
for (i = nargs - 1; i >= 0; i--)
{
{
struct type *value_type = value_enclosing_type (args[i]);
struct type *arg_type = check_typedef (value_type);
- int container_len = (TYPE_LENGTH (value_type) + 3) & ~3;
+ int container_len = (TYPE_LENGTH (arg_type) + 3) & ~3;
sp -= container_len;
- write_memory (sp, value_contents_writeable (args[i]), container_len);
+ write_memory (sp, value_contents (args[i]), container_len);
}
/* Initialize R0, R1, and R2 to the first 3 words of parameters. */
/* Store struct value address. */
- if (struct_return)
+ if (return_method == return_method_struct)
regcache_cooked_write_unsigned (regcache, BFIN_P0_REGNUM, struct_addr);
/* Set the dummy return value to bp_addr.
static int
bfin_reg_to_regnum (struct gdbarch *gdbarch, int reg)
{
- if (reg > ARRAY_SIZE (map_gcc_gdb))
- return 0;
+ if (reg < 0 || reg >= ARRAY_SIZE (map_gcc_gdb))
+ return -1;
return map_gcc_gdb[reg];
}
-/* This function implements the BREAKPOINT_FROM_PC macro. It returns
- a pointer to a string of bytes that encode a breakpoint instruction,
- stores the length of the string to *lenptr, and adjusts the program
- counter (if necessary) to point to the actual memory location where
- the breakpoint should be inserted. */
+/* Implement the breakpoint_kind_from_pc gdbarch method. */
-static const unsigned char *
-bfin_breakpoint_from_pc (struct gdbarch *gdbarch,
- CORE_ADDR *pcptr, int *lenptr)
+static int
+bfin_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr)
{
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
unsigned short iw;
- static unsigned char bfin_breakpoint[] = {0xa1, 0x00, 0x00, 0x00};
- static unsigned char bfin_sim_breakpoint[] = {0x25, 0x00, 0x00, 0x00};
iw = read_memory_unsigned_integer (*pcptr, 2, byte_order);
if ((iw & 0xf000) >= 0xc000)
/* 32-bit instruction. */
- *lenptr = 4;
+ return 4;
else
- *lenptr = 2;
+ return 2;
+}
+
+/* Implement the sw_breakpoint_from_kind gdbarch method. */
+
+static const gdb_byte *
+bfin_sw_breakpoint_from_kind (struct gdbarch *gdbarch, int kind, int *size)
+{
+ static unsigned char bfin_breakpoint[] = {0xa1, 0x00, 0x00, 0x00};
+ static unsigned char bfin_sim_breakpoint[] = {0x25, 0x00, 0x00, 0x00};
+
+ *size = kind;
if (strcmp (target_shortname, "sim") == 0)
return bfin_sim_breakpoint;
struct regcache *regs,
gdb_byte *dst)
{
- struct gdbarch *gdbarch = get_regcache_arch (regs);
+ struct gdbarch *gdbarch = regs->arch ();
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
bfd_byte *valbuf = dst;
int len = TYPE_LENGTH (type);
while (len > 0)
{
- regcache_cooked_write (regs, regno++, valbuf);
+ regs->cooked_write (regno++, valbuf);
len -= 4;
valbuf += 4;
}
}
static enum register_status
-bfin_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
+bfin_pseudo_register_read (struct gdbarch *gdbarch, readable_regcache *regcache,
int regnum, gdb_byte *buffer)
{
- gdb_byte *buf = (gdb_byte *) alloca (MAX_REGISTER_SIZE);
+ gdb_byte buf[BFIN_MAX_REGISTER_SIZE];
enum register_status status;
if (regnum != BFIN_CC_REGNUM)
_("invalid register number %d"), regnum);
/* Extract the CC bit from the ASTAT register. */
- status = regcache_raw_read (regcache, BFIN_ASTAT_REGNUM, buf);
+ status = regcache->raw_read (BFIN_ASTAT_REGNUM, buf);
if (status == REG_VALID)
{
buffer[1] = buffer[2] = buffer[3] = 0;
bfin_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
int regnum, const gdb_byte *buffer)
{
- gdb_byte *buf = (gdb_byte *) alloca (MAX_REGISTER_SIZE);
+ gdb_byte buf[BFIN_MAX_REGISTER_SIZE];
if (regnum != BFIN_CC_REGNUM)
internal_error (__FILE__, __LINE__,
_("invalid register number %d"), regnum);
/* Overlay the CC bit in the ASTAT register. */
- regcache_raw_read (regcache, BFIN_ASTAT_REGNUM, buf);
+ regcache->raw_read (BFIN_ASTAT_REGNUM, buf);
buf[0] = (buf[0] & ~ASTAT_CC) | ((buffer[0] & 1) << ASTAT_CC_POS);
- regcache_raw_write (regcache, BFIN_ASTAT_REGNUM, buf);
+ regcache->raw_write (BFIN_ASTAT_REGNUM, buf);
}
static CORE_ADDR
bfin_frame_args_address
};
-static struct frame_id
-bfin_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
-{
- CORE_ADDR sp;
-
- sp = get_frame_register_unsigned (this_frame, BFIN_SP_REGNUM);
-
- return frame_id_build (sp, get_frame_pc (this_frame));
-}
-
-static CORE_ADDR
-bfin_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
-{
- return frame_unwind_register_unsigned (next_frame, BFIN_PC_REGNUM);
-}
-
static CORE_ADDR
bfin_frame_align (struct gdbarch *gdbarch, CORE_ADDR address)
{
{
struct gdbarch_tdep *tdep;
struct gdbarch *gdbarch;
- int elf_flags;
enum bfin_abi abi;
- /* Extract the ELF flags, if available. */
- if (info.abfd && bfd_get_flavour (info.abfd) == bfd_target_elf_flavour)
- elf_flags = elf_elfheader (info.abfd)->e_flags;
- else
- elf_flags = 0;
-
abi = BFIN_ABI_FLAT;
/* If there is already a candidate, use it. */
return arches->gdbarch;
}
- tdep = XMALLOC (struct gdbarch_tdep);
+ tdep = XCNEW (struct gdbarch_tdep);
gdbarch = gdbarch_alloc (&info, tdep);
tdep->bfin_abi = abi;
set_gdbarch_dwarf2_reg_to_regnum (gdbarch, bfin_reg_to_regnum);
set_gdbarch_register_name (gdbarch, bfin_register_name);
set_gdbarch_register_type (gdbarch, bfin_register_type);
- set_gdbarch_dummy_id (gdbarch, bfin_dummy_id);
set_gdbarch_push_dummy_call (gdbarch, bfin_push_dummy_call);
set_gdbarch_believe_pcc_promotion (gdbarch, 1);
set_gdbarch_return_value (gdbarch, bfin_return_value);
set_gdbarch_skip_prologue (gdbarch, bfin_skip_prologue);
set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
- set_gdbarch_breakpoint_from_pc (gdbarch, bfin_breakpoint_from_pc);
+ set_gdbarch_breakpoint_kind_from_pc (gdbarch, bfin_breakpoint_kind_from_pc);
+ set_gdbarch_sw_breakpoint_from_kind (gdbarch, bfin_sw_breakpoint_from_kind);
set_gdbarch_decr_pc_after_break (gdbarch, 2);
set_gdbarch_frame_args_skip (gdbarch, 8);
- set_gdbarch_unwind_pc (gdbarch, bfin_unwind_pc);
set_gdbarch_frame_align (gdbarch, bfin_frame_align);
- set_gdbarch_print_insn (gdbarch, print_insn_bfin);
/* Hook in ABI-specific overrides, if they have been registered. */
gdbarch_init_osabi (info, gdbarch);
return gdbarch;
}
-/* Provide a prototype to silence -Wmissing-prototypes. */
-extern initialize_file_ftype _initialize_bfin_tdep;
-
void
_initialize_bfin_tdep (void)
{