/* Target-dependent code for Motorola 68HC11 & 68HC12
- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009,
- 2010, 2011 Free Software Foundation, Inc.
+ Copyright (C) 1999-2019 Free Software Foundation, Inc.
Contributed by Stephane Carrez, stcarrez@nerim.fr
#include "gdbtypes.h"
#include "gdbcmd.h"
#include "gdbcore.h"
-#include "gdb_string.h"
#include "value.h"
#include "inferior.h"
#include "dis-asm.h"
#define SOFT_D32_REGNUM (SOFT_D1_REGNUM+31)
#define M68HC11_MAX_SOFT_REGS 32
-#define M68HC11_NUM_REGS (8)
+#define M68HC11_NUM_REGS (M68HC11_LAST_HARD_REG + 1)
#define M68HC11_NUM_PSEUDO_REGS (M68HC11_MAX_SOFT_REGS+5)
#define M68HC11_ALL_REGS (M68HC11_NUM_REGS+M68HC11_NUM_PSEUDO_REGS)
/* Table of registers for 68HC11. This includes the hard registers
and the soft registers used by GCC. */
-static char *
+static const char *
m68hc11_register_names[] =
{
"x", "d", "y", "sp", "pc", "a", "b",
static void
m68hc11_get_register_info (struct m68hc11_soft_reg *reg, const char *name)
{
- struct minimal_symbol *msymbol;
+ struct bound_minimal_symbol msymbol;
msymbol = lookup_minimal_symbol (name, NULL, NULL);
- if (msymbol)
+ if (msymbol.minsym)
{
- reg->addr = SYMBOL_VALUE_ADDRESS (msymbol);
+ reg->addr = BMSYMBOL_VALUE_ADDRESS (msymbol);
reg->name = xstrdup (name);
/* Keep track of the address range for soft registers. */
{
char buf[10];
- sprintf (buf, "_.d%d", i - SOFT_D1_REGNUM + 1);
+ xsnprintf (buf, sizeof (buf), "_.d%d", i - SOFT_D1_REGNUM + 1);
m68hc11_get_register_info (&soft_regs[i], buf);
}
/* Fetch a pseudo register. The 68hc11 soft registers are treated like
pseudo registers. They are located in memory. Translate the register
fetch into a memory read. */
-static void
+static enum register_status
m68hc11_pseudo_register_read (struct gdbarch *gdbarch,
- struct regcache *regcache,
+ readable_regcache *regcache,
int regno, gdb_byte *buf)
{
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
{
ULONGEST pc;
const int regsize = 4;
+ enum register_status status;
- regcache_cooked_read_unsigned (regcache, HARD_PC_REGNUM, &pc);
+ status = regcache->cooked_read (HARD_PC_REGNUM, &pc);
+ if (status != REG_VALID)
+ return status;
if (pc >= 0x8000 && pc < 0xc000)
{
ULONGEST page;
- regcache_cooked_read_unsigned (regcache, HARD_PAGE_REGNUM, &page);
+ regcache->cooked_read (HARD_PAGE_REGNUM, &page);
pc -= 0x8000;
pc += (page << 14);
pc += 0x1000000;
}
store_unsigned_integer (buf, regsize, byte_order, pc);
- return;
+ return REG_VALID;
}
m68hc11_initialize_register_info ();
{
memset (buf, 0, 2);
}
+
+ return REG_VALID;
}
/* Store a pseudo register. Translate the register store
if (regno == M68HC12_HARD_PC_REGNUM)
{
const int regsize = 4;
- char *tmp = alloca (regsize);
+ gdb_byte *tmp = (gdb_byte *) alloca (regsize);
CORE_ADDR pc;
memcpy (tmp, buf, regsize);
if (soft_regs[regno].name)
{
const int regsize = 2;
- char *tmp = alloca (regsize);
+ gdb_byte *tmp = (gdb_byte *) alloca (regsize);
memcpy (tmp, buf, regsize);
target_write_memory (soft_regs[regno].addr, tmp, regsize);
}
return m68hc11_register_names[reg_nr];
}
-static const unsigned char *
-m68hc11_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr,
- int *lenptr)
-{
- static unsigned char breakpoint[] = {0x0};
-
- *lenptr = sizeof (breakpoint);
- return breakpoint;
-}
+constexpr gdb_byte m68hc11_break_insn[] = {0x0};
+typedef BP_MANIPULATION (m68hc11_break_insn) m68hc11_breakpoint;
\f
/* 68HC11 & 68HC12 prologue analysis. */
static enum insn_return_kind
m68hc11_get_return_insn (CORE_ADDR pc)
{
- struct minimal_symbol *sym;
+ struct bound_minimal_symbol sym;
/* A flag indicating that this is a STO_M68HC12_FAR or STO_M68HC12_INTERRUPT
function is stored by elfread.c in the high bit of the info field.
Use this to decide which instruction the function uses to return. */
sym = lookup_minimal_symbol_by_pc (pc);
- if (sym == 0)
+ if (sym.minsym == 0)
return RETURN_RTS;
- if (MSYMBOL_IS_RTC (sym))
+ if (MSYMBOL_IS_RTC (sym.minsym))
return RETURN_RTC;
- else if (MSYMBOL_IS_RTI (sym))
+ else if (MSYMBOL_IS_RTI (sym.minsym))
return RETURN_RTI;
else
return RETURN_RTS;
return pc;
}
-static CORE_ADDR
-m68hc11_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
-{
- ULONGEST pc;
-
- pc = frame_unwind_register_unsigned (next_frame,
- gdbarch_pc_regnum (gdbarch));
- return pc;
-}
-
/* Put here the code to store, into fi->saved_regs, the addresses of
the saved registers of frame described by FRAME_INFO. This
includes special registers such as pc and fp saved in special ways
int i;
if ((*this_prologue_cache))
- return (*this_prologue_cache);
+ return (struct m68hc11_unwind_cache *) (*this_prologue_cache);
info = FRAME_OBSTACK_ZALLOC (struct m68hc11_unwind_cache);
(*this_prologue_cache) = info;
/* Adjust all the saved registers so that they contain addresses and not
offsets. */
- for (i = 0;
- i < gdbarch_num_regs (gdbarch)
- + gdbarch_num_pseudo_regs (gdbarch) - 1;
- i++)
+ for (i = 0; i < gdbarch_num_cooked_regs (gdbarch); i++)
if (trad_frame_addr_p (info->saved_regs, i))
{
info->saved_regs[i].addr += this_base;
CORE_ADDR page;
release_value (value);
- value_free (value);
value = trad_frame_get_prev_register (this_frame, info->saved_regs,
HARD_PAGE_REGNUM);
page = value_as_long (value);
release_value (value);
- value_free (value);
pc -= 0x08000;
pc += ((page & 0x0ff) << 14);
static const struct frame_unwind m68hc11_frame_unwind = {
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
m68hc11_frame_this_id,
m68hc11_frame_prev_register,
NULL,
m68hc11_frame_args_address
};
-static CORE_ADDR
-m68hc11_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
-{
- ULONGEST sp;
- sp = frame_unwind_register_unsigned (next_frame, HARD_SP_REGNUM);
- return sp;
-}
-
/* Assuming THIS_FRAME is a dummy, return the frame ID of that dummy
frame. The frame ID's base needs to match the TOS value saved by
save_dummy_frame_tos(), and the PC match the dummy frame's breakpoint. */
m68hc11_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)
{
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
int argnum;
int first_stack_argnum;
struct type *type;
- char *val;
- int len;
- char buf[2];
+ const gdb_byte *val;
+ gdb_byte buf[2];
first_stack_argnum = 0;
- if (struct_return)
- {
- regcache_cooked_write_unsigned (regcache, HARD_D_REGNUM, struct_addr);
- }
+ if (return_method == return_method_struct)
+ regcache_cooked_write_unsigned (regcache, HARD_D_REGNUM, struct_addr);
else if (nargs > 0)
{
type = value_type (args[0]);
- len = TYPE_LENGTH (type);
/* First argument is passed in D and X registers. */
- if (len <= 4)
+ if (TYPE_LENGTH (type) <= 4)
{
ULONGEST v;
v = extract_unsigned_integer (value_contents (args[0]),
- len, byte_order);
+ TYPE_LENGTH (type), byte_order);
first_stack_argnum = 1;
regcache_cooked_write_unsigned (regcache, HARD_D_REGNUM, v);
- if (len > 2)
+ if (TYPE_LENGTH (type) > 2)
{
v >>= 16;
regcache_cooked_write_unsigned (regcache, HARD_X_REGNUM, v);
for (argnum = nargs - 1; argnum >= first_stack_argnum; argnum--)
{
type = value_type (args[argnum]);
- len = TYPE_LENGTH (type);
- if (len & 1)
+ if (TYPE_LENGTH (type) & 1)
{
- static char zero = 0;
+ static gdb_byte zero = 0;
sp--;
write_memory (sp, &zero, 1);
}
- val = (char*) value_contents (args[argnum]);
- sp -= len;
- write_memory (sp, val, len);
+ val = value_contents (args[argnum]);
+ sp -= TYPE_LENGTH (type);
+ write_memory (sp, val, TYPE_LENGTH (type));
}
/* Store return address. */
static void
m68hc11_store_return_value (struct type *type, struct regcache *regcache,
- const void *valbuf)
+ const gdb_byte *valbuf)
{
int len;
/* First argument is passed in D and X registers. */
if (len <= 2)
- regcache_raw_write_part (regcache, HARD_D_REGNUM, 2 - len, len, valbuf);
+ regcache->raw_write_part (HARD_D_REGNUM, 2 - len, len, valbuf);
else if (len <= 4)
{
- regcache_raw_write_part (regcache, HARD_X_REGNUM, 4 - len,
- len - 2, valbuf);
- regcache_raw_write (regcache, HARD_D_REGNUM, (char*) valbuf + (len - 2));
+ regcache->raw_write_part (HARD_X_REGNUM, 4 - len, len - 2, valbuf);
+ regcache->raw_write (HARD_D_REGNUM, valbuf + (len - 2));
}
else
error (_("return of value > 4 is not supported."));
m68hc11_extract_return_value (struct type *type, struct regcache *regcache,
void *valbuf)
{
- int len = TYPE_LENGTH (type);
- char buf[M68HC11_REG_SIZE];
+ gdb_byte buf[M68HC11_REG_SIZE];
- regcache_raw_read (regcache, HARD_D_REGNUM, buf);
- switch (len)
+ regcache->raw_read (HARD_D_REGNUM, buf);
+ switch (TYPE_LENGTH (type))
{
case 1:
memcpy (valbuf, buf + 1, 1);
case 3:
memcpy ((char*) valbuf + 1, buf, 2);
- regcache_raw_read (regcache, HARD_X_REGNUM, buf);
+ regcache->raw_read (HARD_X_REGNUM, buf);
memcpy (valbuf, buf + 1, 1);
break;
case 4:
memcpy ((char*) valbuf + 2, buf, 2);
- regcache_raw_read (regcache, HARD_X_REGNUM, buf);
+ regcache->raw_read (HARD_X_REGNUM, buf);
memcpy (valbuf, buf, 2);
break;
}
static enum return_value_convention
-m68hc11_return_value (struct gdbarch *gdbarch, struct type *func_type,
+m68hc11_return_value (struct gdbarch *gdbarch, struct value *function,
struct type *valtype, struct regcache *regcache,
gdb_byte *readbuf, const gdb_byte *writebuf)
{
if (flags & STO_M68HC12_INTERRUPT)
MSYMBOL_SET_RTI (msym);
}
-
-static int
-gdb_print_insn_m68hc11 (bfd_vma memaddr, disassemble_info *info)
-{
- if (info->arch == bfd_arch_m68hc11)
- return print_insn_m68hc11 (memaddr, info);
- else
- return print_insn_m68hc12 (memaddr, info);
-}
-
\f
/* 68HC11/68HC12 register groups.
}
/* Need a new architecture. Fill in a target specific vector. */
- tdep = (struct gdbarch_tdep *) xmalloc (sizeof (struct gdbarch_tdep));
+ tdep = XCNEW (struct gdbarch_tdep);
gdbarch = gdbarch_alloc (&info, tdep);
tdep->elf_flags = elf_flags;
set_gdbarch_short_bit (gdbarch, 16);
set_gdbarch_int_bit (gdbarch, elf_flags & E_M68HC11_I32 ? 32 : 16);
set_gdbarch_float_bit (gdbarch, 32);
- set_gdbarch_double_bit (gdbarch, elf_flags & E_M68HC11_F64 ? 64 : 32);
+ if (elf_flags & E_M68HC11_F64)
+ {
+ set_gdbarch_double_bit (gdbarch, 64);
+ set_gdbarch_double_format (gdbarch, floatformats_ieee_double);
+ }
+ else
+ {
+ set_gdbarch_double_bit (gdbarch, 32);
+ set_gdbarch_double_format (gdbarch, floatformats_ieee_single);
+ }
set_gdbarch_long_double_bit (gdbarch, 64);
set_gdbarch_long_bit (gdbarch, 32);
set_gdbarch_ptr_bit (gdbarch, 16);
/* Characters are unsigned. */
set_gdbarch_char_signed (gdbarch, 0);
- set_gdbarch_unwind_pc (gdbarch, m68hc11_unwind_pc);
- set_gdbarch_unwind_sp (gdbarch, m68hc11_unwind_sp);
-
/* Set register info. */
set_gdbarch_fp0_regnum (gdbarch, -1);
set_gdbarch_return_value (gdbarch, m68hc11_return_value);
set_gdbarch_skip_prologue (gdbarch, m68hc11_skip_prologue);
set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
- set_gdbarch_breakpoint_from_pc (gdbarch, m68hc11_breakpoint_from_pc);
- set_gdbarch_print_insn (gdbarch, gdb_print_insn_m68hc11);
+ set_gdbarch_breakpoint_kind_from_pc (gdbarch,
+ m68hc11_breakpoint::kind_from_pc);
+ set_gdbarch_sw_breakpoint_from_kind (gdbarch,
+ m68hc11_breakpoint::bp_from_kind);
m68hc11_add_reggroups (gdbarch);
set_gdbarch_register_reggroup_p (gdbarch, m68hc11_register_reggroup_p);
PUSH_DUMMY_CALL, and saved by generic_save_dummy_frame_tos. */
set_gdbarch_dummy_id (gdbarch, m68hc11_dummy_id);
- /* Return the unwound PC value. */
- set_gdbarch_unwind_pc (gdbarch, m68hc11_unwind_pc);
-
/* Minsymbol frobbing. */
set_gdbarch_elf_make_msymbol_special (gdbarch,
m68hc11_elf_make_msymbol_special);
return gdbarch;
}
-/* -Wmissing-prototypes */
-extern initialize_file_ftype _initialize_m68hc11_tdep;
-
void
_initialize_m68hc11_tdep (void)
{