/* Target-dependent code for the Toshiba MeP for GDB, the GNU debugger.
- Copyright (C) 2001-2014 Free Software Foundation, Inc.
+ Copyright (C) 2001-2020 Free Software Foundation, Inc.
Contributed by Red Hat, Inc.
#include "gdbtypes.h"
#include "gdbcmd.h"
#include "gdbcore.h"
-#include <string.h>
#include "value.h"
#include "inferior.h"
#include "dis-asm.h"
#include "arch-utils.h"
#include "regcache.h"
#include "remote.h"
-#include "floatformat.h"
#include "sim-regno.h"
#include "disasm.h"
#include "trad-frame.h"
#include "cgen/bitset.h"
#include "infcall.h"
-#include "gdb_assert.h"
-
/* Get the user's customized MeP coprocessor register names from
libopcodes. */
#include "opcodes/mep-desc.h"
/* Given a hardware table entry HW representing a register set, return
a pointer to the keyword table with all the register names. If HW
- is NULL, return NULL, to propage the "no such register set" info
+ is NULL, return NULL, to propagate the "no such register set" info
along. */
static CGEN_KEYWORD *
register_set_keyword_table (const CGEN_HW_ENTRY *hw)
/* Given a keyword table KEYWORD and a register number REGNUM, return
the name of the register, or "" if KEYWORD contains no register
whose number is REGNUM. */
-static char *
+static const char *
register_name_from_keyword (CGEN_KEYWORD *keyword_table, int regnum)
{
const CGEN_KEYWORD_ENTRY *entry
mep_debug_reg_to_regnum (struct gdbarch *gdbarch, int debug_reg)
{
/* The debug info uses the raw register numbers. */
- return mep_raw_to_pseudo[debug_reg];
+ if (debug_reg >= 0 && debug_reg < ARRAY_SIZE (mep_raw_to_pseudo))
+ return mep_raw_to_pseudo[debug_reg];
+ return -1;
}
ULONGEST regval;
regcache_cooked_read_unsigned (get_current_regcache (),
MEP_MODULE_REGNUM, ®val);
- return regval;
+ return (CONFIG_ATTR) regval;
}
else
return gdbarch_tdep (target_gdbarch ())->me_module;
static const char *
mep_register_name (struct gdbarch *gdbarch, int regnr)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-
/* General-purpose registers. */
static const char *gpr_names[] = {
"r0", "r1", "r2", "r3", /* 0 */
return builtin_type (gdbarch)->builtin_uint32;
}
-
-static CORE_ADDR
-mep_read_pc (struct regcache *regcache)
-{
- ULONGEST pc;
- regcache_cooked_read_unsigned (regcache, MEP_PC_REGNUM, &pc);
- return pc;
-}
-
static enum register_status
mep_pseudo_cr32_read (struct gdbarch *gdbarch,
- struct regcache *regcache,
+ readable_regcache *regcache,
int cookednum,
- void *buf)
+ gdb_byte *buf)
{
enum register_status status;
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
gdb_assert (TYPE_LENGTH (register_type (gdbarch, rawnum)) == sizeof (buf64));
gdb_assert (TYPE_LENGTH (register_type (gdbarch, cookednum)) == 4);
- status = regcache_raw_read (regcache, rawnum, buf64);
+ status = regcache->raw_read (rawnum, buf64);
if (status == REG_VALID)
{
/* Slow, but legible. */
static enum register_status
mep_pseudo_cr64_read (struct gdbarch *gdbarch,
- struct regcache *regcache,
+ readable_regcache *regcache,
int cookednum,
- void *buf)
+ gdb_byte *buf)
{
- return regcache_raw_read (regcache, mep_pseudo_to_raw[cookednum], buf);
+ return regcache->raw_read (mep_pseudo_to_raw[cookednum], buf);
}
static enum register_status
mep_pseudo_register_read (struct gdbarch *gdbarch,
- struct regcache *regcache,
+ readable_regcache *regcache,
int cookednum,
gdb_byte *buf)
{
if (IS_CSR_REGNUM (cookednum)
|| IS_CCR_REGNUM (cookednum))
- return regcache_raw_read (regcache, mep_pseudo_to_raw[cookednum], buf);
+ return regcache->raw_read (mep_pseudo_to_raw[cookednum], buf);
else if (IS_CR32_REGNUM (cookednum)
|| IS_FP_CR32_REGNUM (cookednum))
return mep_pseudo_cr32_read (gdbarch, regcache, cookednum, buf);
mep_pseudo_csr_write (struct gdbarch *gdbarch,
struct regcache *regcache,
int cookednum,
- const void *buf)
+ const gdb_byte *buf)
{
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
int size = register_size (gdbarch, cookednum);
mep_pseudo_cr32_write (struct gdbarch *gdbarch,
struct regcache *regcache,
int cookednum,
- const void *buf)
+ const gdb_byte *buf)
{
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
/* Expand the 32-bit value into a 64-bit value, and write that to
/* Slow, but legible. */
store_unsigned_integer (buf64, 8, byte_order,
extract_unsigned_integer (buf, 4, byte_order));
- regcache_raw_write (regcache, rawnum, buf64);
+ regcache->raw_write (rawnum, buf64);
}
mep_pseudo_cr64_write (struct gdbarch *gdbarch,
struct regcache *regcache,
int cookednum,
- const void *buf)
+ const gdb_byte *buf)
{
- regcache_raw_write (regcache, mep_pseudo_to_raw[cookednum], buf);
+ regcache->raw_write (mep_pseudo_to_raw[cookednum], buf);
}
|| IS_FP_CR64_REGNUM (cookednum))
mep_pseudo_cr64_write (gdbarch, regcache, cookednum, buf);
else if (IS_CCR_REGNUM (cookednum))
- regcache_raw_write (regcache, mep_pseudo_to_raw[cookednum], buf);
+ regcache->raw_write (mep_pseudo_to_raw[cookednum], buf);
else
gdb_assert_not_reached ("unexpected pseudo register");
}
\f
/* Disassembly. */
-/* The mep disassembler needs to know about the section in order to
- work correctly. */
static int
mep_gdb_print_insn (bfd_vma pc, disassemble_info * info)
{
struct obj_section * s = find_pc_section (pc);
+ info->arch = bfd_arch_mep;
if (s)
{
/* The libopcodes disassembly code uses the section to find the
the me_module index, and the me_module index to select the
right instructions to print. */
info->section = s->the_bfd_section;
- info->arch = bfd_arch_mep;
-
- return print_insn_mep (pc, info);
}
-
- return 0;
+
+ return print_insn_mep (pc, info);
}
\f
{
return (is_arg_reg (value)
&& pv_is_register (addr, MEP_SP_REGNUM)
- && ! pv_area_find_reg (stack, gdbarch, value.reg, 0));
+ && ! stack->find_reg (gdbarch, value.reg, 0));
}
/* Function for finding saved registers in a 'struct pv_area'; we pass
- this to pv_area_scan.
+ this to pv_area::scan.
If VALUE is a saved register, ADDR says it was saved at a constant
offset from the frame base, and SIZE indicates that the whole
{
CORE_ADDR pc;
unsigned long insn;
- int rn;
- int found_lp = 0;
pv_t reg[MEP_NUM_REGS];
- struct pv_area *stack;
- struct cleanup *back_to;
CORE_ADDR after_last_frame_setup_insn = start_pc;
memset (result, 0, sizeof (*result));
result->gdbarch = gdbarch;
- for (rn = 0; rn < MEP_NUM_REGS; rn++)
+ for (int rn = 0; rn < MEP_NUM_REGS; rn++)
{
reg[rn] = pv_register (rn, 0);
result->reg_offset[rn] = 1;
}
- stack = make_pv_area (MEP_SP_REGNUM, gdbarch_addr_bit (gdbarch));
- back_to = make_cleanup_free_pv_area (stack);
+ pv_area stack (MEP_SP_REGNUM, gdbarch_addr_bit (gdbarch));
pc = start_pc;
while (pc < limit_pc)
/* If simulating this store would require us to forget
everything we know about the stack frame in the name of
accuracy, it would be better to just quit now. */
- if (pv_area_store_would_trash (stack, reg[rm]))
+ if (stack.store_would_trash (reg[rm]))
break;
- if (is_arg_spill (gdbarch, reg[rn], reg[rm], stack))
+ if (is_arg_spill (gdbarch, reg[rn], reg[rm], &stack))
after_last_frame_setup_insn = next_pc;
- pv_area_store (stack, reg[rm], 4, reg[rn]);
+ stack.store (reg[rm], 4, reg[rn]);
}
else if (IS_SW_IMMD (insn))
{
/* If simulating this store would require us to forget
everything we know about the stack frame in the name of
accuracy, it would be better to just quit now. */
- if (pv_area_store_would_trash (stack, addr))
+ if (stack.store_would_trash (addr))
break;
- if (is_arg_spill (gdbarch, reg[rn], addr, stack))
+ if (is_arg_spill (gdbarch, reg[rn], addr, &stack))
after_last_frame_setup_insn = next_pc;
- pv_area_store (stack, addr, 4, reg[rn]);
+ stack.store (addr, 4, reg[rn]);
}
else if (IS_MOV (insn))
{
: (gdb_assert (IS_SW (insn)), 4));
pv_t addr = pv_add_constant (reg[rm], disp);
- if (pv_area_store_would_trash (stack, addr))
+ if (stack.store_would_trash (addr))
break;
- if (is_arg_spill (gdbarch, reg[rn], addr, stack))
+ if (is_arg_spill (gdbarch, reg[rn], addr, &stack))
after_last_frame_setup_insn = next_pc;
- pv_area_store (stack, addr, size, reg[rn]);
+ stack.store (addr, size, reg[rn]);
}
else if (IS_LDC (insn))
{
int offset = LW_OFFSET (insn);
pv_t addr = pv_add_constant (reg[rm], offset);
- reg[rn] = pv_area_fetch (stack, addr, 4);
+ reg[rn] = stack.fetch (addr, 4);
}
else if (IS_BRA (insn) && BRA_DISP (insn) > 0)
{
}
/* Record where all the registers were saved. */
- pv_area_scan (stack, check_for_saved, (void *) result);
+ stack.scan (check_for_saved, (void *) result);
result->prologue_end = after_last_frame_setup_insn;
-
- do_cleanups (back_to);
}
\f
/* Breakpoints. */
+constexpr gdb_byte mep_break_insn[] = { 0x70, 0x32 };
-static const unsigned char *
-mep_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR * pcptr, int *lenptr)
-{
- static unsigned char breakpoint[] = { 0x70, 0x32 };
- *lenptr = sizeof (breakpoint);
- return breakpoint;
-}
-
+typedef BP_MANIPULATION (mep_break_insn) mep_breakpoint;
\f
/* Frames and frame unwinding. */
stop_addr = func_start;
mep_analyze_prologue (get_frame_arch (this_frame),
- func_start, stop_addr, *this_prologue_cache);
+ func_start, stop_addr,
+ (struct mep_prologue *) *this_prologue_cache);
}
- return *this_prologue_cache;
+ return (struct mep_prologue *) *this_prologue_cache;
}
MEP_LP_REGNUM);
lp = value_as_long (value);
release_value (value);
- value_free (value);
return frame_unwind_got_constant (this_frame, regnum, lp & ~1);
}
psw = value_as_long (value);
release_value (value);
- value_free (value);
/* Get the LP's value, too. */
value = get_frame_register_value (this_frame, MEP_LP_REGNUM);
lp = value_as_long (value);
release_value (value);
- value_free (value);
/* If LP.LTOM is set, then toggle PSW.OM. */
if (lp & 0x1)
default_frame_sniffer
};
-
-/* Our general unwinding function can handle unwinding the PC. */
-static CORE_ADDR
-mep_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
-{
- return frame_unwind_register_unsigned (next_frame, MEP_PC_REGNUM);
-}
-
-
-/* Our general unwinding function can handle unwinding the SP. */
-static CORE_ADDR
-mep_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
-{
- return frame_unwind_register_unsigned (next_frame, MEP_SP_REGNUM);
-}
-
-
\f
/* Return values. */
offset = 0;
/* Return values that do fit in a single register are returned in R0. */
- regcache_cooked_read_part (regcache, MEP_R0_REGNUM,
- offset, TYPE_LENGTH (type),
- valbuf);
+ regcache->cooked_read_part (MEP_R0_REGNUM, offset, TYPE_LENGTH (type),
+ valbuf);
}
else
offset = 0;
- regcache_cooked_write_part (regcache, MEP_R0_REGNUM,
- offset, TYPE_LENGTH (type),
- valbuf);
+ regcache->cooked_write_part (MEP_R0_REGNUM, offset, TYPE_LENGTH (type),
+ valbuf);
}
/* Return values larger than a single register are returned in
mep_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
struct regcache *regcache, CORE_ADDR bp_addr,
int argc, struct value **argv, 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);
CORE_ADDR *copy = (CORE_ADDR *) alloca (argc * sizeof (copy[0]));
- CORE_ADDR func_addr = find_function_addr (function, NULL);
int i;
/* The number of the next register available to hold an argument. */
/* If we're returning a structure by value, push the pointer to the
buffer as the first argument. */
- if (struct_return)
+ if (return_method == return_method_struct)
{
regcache_cooked_write_unsigned (regcache, arg_reg, struct_addr);
arg_reg++;
return sp;
}
-
-static struct frame_id
-mep_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
-{
- CORE_ADDR sp = get_frame_register_unsigned (this_frame, MEP_SP_REGNUM);
- return frame_id_build (sp, get_frame_pc (this_frame));
-}
-
-
\f
/* Initialization. */
/* The way to get the me_module code depends on the object file
format. At the moment, we only know how to handle ELF. */
if (bfd_get_flavour (info.abfd) == bfd_target_elf_flavour)
- me_module = elf_elfheader (info.abfd)->e_flags & EF_MEP_INDEX_MASK;
+ {
+ int flag = elf_elfheader (info.abfd)->e_flags & EF_MEP_INDEX_MASK;
+ me_module = (CONFIG_ATTR) flag;
+ }
else
me_module = CONFIG_NONE;
}
if (gdbarch_tdep (arches->gdbarch)->me_module == me_module)
return arches->gdbarch;
- tdep = (struct gdbarch_tdep *) xmalloc (sizeof (struct gdbarch_tdep));
+ tdep = XCNEW (struct gdbarch_tdep);
gdbarch = gdbarch_alloc (&info, tdep);
/* Get a CGEN CPU descriptor for this architecture. */
tdep->me_module = me_module;
/* Register set. */
- set_gdbarch_read_pc (gdbarch, mep_read_pc);
set_gdbarch_num_regs (gdbarch, MEP_NUM_RAW_REGS);
set_gdbarch_pc_regnum (gdbarch, MEP_PC_REGNUM);
set_gdbarch_sp_regnum (gdbarch, MEP_SP_REGNUM);
set_gdbarch_print_insn (gdbarch, mep_gdb_print_insn);
/* Breakpoints. */
- set_gdbarch_breakpoint_from_pc (gdbarch, mep_breakpoint_from_pc);
+ set_gdbarch_breakpoint_kind_from_pc (gdbarch, mep_breakpoint::kind_from_pc);
+ set_gdbarch_sw_breakpoint_from_kind (gdbarch, mep_breakpoint::bp_from_kind);
set_gdbarch_decr_pc_after_break (gdbarch, 0);
set_gdbarch_skip_prologue (gdbarch, mep_skip_prologue);
/* Frames and frame unwinding. */
frame_unwind_append_unwinder (gdbarch, &mep_frame_unwind);
- set_gdbarch_unwind_pc (gdbarch, mep_unwind_pc);
- set_gdbarch_unwind_sp (gdbarch, mep_unwind_sp);
set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
set_gdbarch_frame_args_skip (gdbarch, 0);
/* Inferior function calls. */
set_gdbarch_frame_align (gdbarch, mep_frame_align);
set_gdbarch_push_dummy_call (gdbarch, mep_push_dummy_call);
- set_gdbarch_dummy_id (gdbarch, mep_dummy_id);
return gdbarch;
}
-/* Provide a prototype to silence -Wmissing-prototypes. */
-extern initialize_file_ftype _initialize_mep_tdep;
-
void
_initialize_mep_tdep (void)
{