/* Target-dependent code for Lattice Mico32 processor, for GDB.
Contributed by Jon Beniston <jon@beniston.com>
- Copyright (C) 2009-2012 Free Software Foundation, Inc.
+ Copyright (C) 2009-2023 Free Software Foundation, Inc.
This file is part of GDB.
#include "symfile.h"
#include "remote.h"
#include "gdbcore.h"
-#include "gdb/sim-lm32.h"
-#include "gdb/callback.h"
-#include "gdb/remote-sim.h"
-#include "sim-regno.h"
+#include "sim/sim-lm32.h"
#include "arch-utils.h"
#include "regcache.h"
#include "trad-frame.h"
#include "reggroups.h"
-#include "opcodes/lm32-desc.h"
+#include <algorithm>
+#include "gdbarch.h"
-#include "gdb_string.h"
+/* Make cgen names unique to prevent ODR conflicts with other targets. */
+#define GDB_CGEN_REMAP_PREFIX lm32
+#include "cgen-remap.h"
+#include "opcodes/lm32-desc.h"
/* Macros to extract fields from an instruction. */
#define LM32_OPCODE(insn) ((insn >> 26) & 0x3f)
#define LM32_REG2(insn) ((insn >> 11) & 0x1f)
#define LM32_IMM16(insn) ((((long)insn & 0xffff) << 16) >> 16)
-struct gdbarch_tdep
+struct lm32_gdbarch_tdep : gdbarch_tdep_base
{
/* gdbarch target dependent data here. Currently unused for LM32. */
};
/* Size of frame. */
int size;
/* Table indicating the location of each and every register. */
- struct trad_frame_saved_reg *saved_regs;
+ trad_frame_saved_reg *saved_regs;
};
-/* Add the available register groups. */
-
-static void
-lm32_add_reggroups (struct gdbarch *gdbarch)
-{
- reggroup_add (gdbarch, general_reggroup);
- reggroup_add (gdbarch, all_reggroup);
- reggroup_add (gdbarch, system_reggroup);
-}
-
/* Return whether a given register is in a given group. */
static int
lm32_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
- struct reggroup *group)
+ const struct reggroup *group)
{
if (group == general_reggroup)
return ((regnum >= SIM_LM32_R0_REGNUM) && (regnum <= SIM_LM32_RA_REGNUM))
|| (regnum == SIM_LM32_PC_REGNUM);
else if (group == system_reggroup)
- return ((regnum >= SIM_LM32_EA_REGNUM) && (regnum <= SIM_LM32_BA_REGNUM))
+ return ((regnum >= SIM_LM32_BA_REGNUM) && (regnum <= SIM_LM32_EA_REGNUM))
|| ((regnum >= SIM_LM32_EID_REGNUM) && (regnum <= SIM_LM32_IP_REGNUM));
return default_register_reggroup_p (gdbarch, regnum, group);
}
static const char *
lm32_register_name (struct gdbarch *gdbarch, int reg_nr)
{
- static char *register_names[] = {
+ static const char *register_names[] = {
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
"r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
"PC", "EID", "EBA", "DEBA", "IE", "IM", "IP"
};
- if ((reg_nr < 0) || (reg_nr >= ARRAY_SIZE (register_names)))
- return NULL;
- else
- return register_names[reg_nr];
+ gdb_static_assert (ARRAY_SIZE (register_names) == SIM_LM32_NUM_REGS);
+ return register_names[reg_nr];
}
/* Return type of register. */
/* Any stack displaced store is likely part of the prologue.
Record that the register is being saved, and the offset
into the stack. */
- info->saved_regs[LM32_REG1 (instruction)].addr =
- LM32_IMM16 (instruction);
+ info->saved_regs[LM32_REG1 (instruction)].set_addr (LM32_IMM16 (instruction));
}
else if ((LM32_OPCODE (instruction) == OP_ADDI)
&& (LM32_REG1 (instruction) == SIM_LM32_SP_REGNUM))
{
CORE_ADDR func_addr, limit_pc;
struct lm32_frame_cache frame_info;
- struct trad_frame_saved_reg saved_regs[SIM_LM32_NUM_REGS];
+ trad_frame_saved_reg saved_regs[SIM_LM32_NUM_REGS];
/* See if we can determine the end of the prologue via the symbol table.
If so, then return either PC, or the PC after the prologue, whichever
CORE_ADDR post_prologue_pc
= skip_prologue_using_sal (gdbarch, func_addr);
if (post_prologue_pc != 0)
- return max (pc, post_prologue_pc);
+ return std::max (pc, post_prologue_pc);
}
/* Can't determine prologue from the symbol table, need to examine
}
/* Create a breakpoint instruction. */
+constexpr gdb_byte lm32_break_insn[4] = { OP_RAISE << 2, 0, 0, 2 };
-static const gdb_byte *
-lm32_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr,
- int *lenptr)
-{
- static const gdb_byte breakpoint[4] = { OP_RAISE << 2, 0, 0, 2 };
+typedef BP_MANIPULATION (lm32_break_insn) lm32_breakpoint;
- *lenptr = sizeof (breakpoint);
- return breakpoint;
-}
/* Setup registers and stack for faking a call to a function in the
inferior. */
lm32_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 first_arg_reg = SIM_LM32_R1_REGNUM;
/* If we're returning a large struct, a pointer to the address to
store it at is passed as a first hidden parameter. */
- if (struct_return)
+ if (return_method == return_method_struct)
{
regcache_cooked_write_unsigned (regcache, first_arg_reg, struct_addr);
first_arg_reg++;
for (i = 0; i < nargs; i++)
{
struct value *arg = args[i];
- struct type *arg_type = check_typedef (value_type (arg));
+ struct type *arg_type = check_typedef (arg->type ());
gdb_byte *contents;
ULONGEST val;
/* Promote small integer types to int. */
- switch (TYPE_CODE (arg_type))
+ switch (arg_type->code ())
{
case TYPE_CODE_INT:
case TYPE_CODE_BOOL:
case TYPE_CODE_CHAR:
case TYPE_CODE_RANGE:
case TYPE_CODE_ENUM:
- if (TYPE_LENGTH (arg_type) < 4)
+ if (arg_type->length () < 4)
{
arg_type = builtin_type (gdbarch)->builtin_int32;
arg = value_cast (arg_type, arg);
/* FIXME: Handle structures. */
- contents = (gdb_byte *) value_contents (arg);
- val = extract_unsigned_integer (contents, TYPE_LENGTH (arg_type),
+ contents = (gdb_byte *) arg->contents ().data ();
+ val = extract_unsigned_integer (contents, arg_type->length (),
byte_order);
/* First num_arg_regs parameters are passed by registers,
- and the rest are passed on the stack. */
+ and the rest are passed on the stack. */
if (i < num_arg_regs)
regcache_cooked_write_unsigned (regcache, first_arg_reg + i, val);
else
{
- write_memory (sp, (void *) &val, TYPE_LENGTH (arg_type));
+ write_memory_unsigned_integer (sp, arg_type->length (), byte_order,
+ val);
sp -= 4;
}
}
lm32_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);
ULONGEST l;
CORE_ADDR return_buffer;
- if (TYPE_CODE (type) != TYPE_CODE_STRUCT
- && TYPE_CODE (type) != TYPE_CODE_UNION
- && TYPE_CODE (type) != TYPE_CODE_ARRAY && TYPE_LENGTH (type) <= 4)
+ if (type->code () != TYPE_CODE_STRUCT
+ && type->code () != TYPE_CODE_UNION
+ && type->code () != TYPE_CODE_ARRAY && type->length () <= 4)
{
/* Return value is returned in a single register. */
regcache_cooked_read_unsigned (regcache, SIM_LM32_R1_REGNUM, &l);
- store_unsigned_integer (valbuf, TYPE_LENGTH (type), byte_order, l);
+ store_unsigned_integer (valbuf, type->length (), byte_order, l);
}
- else if ((TYPE_CODE (type) == TYPE_CODE_INT) && (TYPE_LENGTH (type) == 8))
+ else if ((type->code () == TYPE_CODE_INT) && (type->length () == 8))
{
/* 64-bit values are returned in a register pair. */
regcache_cooked_read_unsigned (regcache, SIM_LM32_R1_REGNUM, &l);
else
{
/* Aggregate types greater than a single register are returned
- in memory. FIXME: Unless they are only 2 regs?. */
+ in memory. FIXME: Unless they are only 2 regs?. */
regcache_cooked_read_unsigned (regcache, SIM_LM32_R1_REGNUM, &l);
return_buffer = l;
- read_memory (return_buffer, valbuf, TYPE_LENGTH (type));
+ read_memory (return_buffer, valbuf, type->length ());
}
}
lm32_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);
ULONGEST val;
- int len = TYPE_LENGTH (type);
+ int len = type->length ();
if (len <= 4)
{
struct type *valtype, struct regcache *regcache,
gdb_byte *readbuf, const gdb_byte *writebuf)
{
- enum type_code code = TYPE_CODE (valtype);
+ enum type_code code = valtype->code ();
if (code == TYPE_CODE_STRUCT
|| code == TYPE_CODE_UNION
- || code == TYPE_CODE_ARRAY || TYPE_LENGTH (valtype) > 8)
+ || code == TYPE_CODE_ARRAY || valtype->length () > 8)
return RETURN_VALUE_STRUCT_CONVENTION;
if (readbuf)
return RETURN_VALUE_REGISTER_CONVENTION;
}
-static CORE_ADDR
-lm32_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
-{
- return frame_unwind_register_unsigned (next_frame, SIM_LM32_PC_REGNUM);
-}
-
-static CORE_ADDR
-lm32_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
-{
- return frame_unwind_register_unsigned (next_frame, SIM_LM32_SP_REGNUM);
-}
-
-static struct frame_id
-lm32_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
-{
- CORE_ADDR sp = get_frame_register_unsigned (this_frame, SIM_LM32_SP_REGNUM);
-
- return frame_id_build (sp, get_frame_pc (this_frame));
-}
-
/* 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
for it IS the sp for the next frame. */
static struct lm32_frame_cache *
-lm32_frame_cache (struct frame_info *this_frame, void **this_prologue_cache)
+lm32_frame_cache (frame_info_ptr this_frame, void **this_prologue_cache)
{
CORE_ADDR current_pc;
ULONGEST prev_sp;
int i;
if ((*this_prologue_cache))
- return (*this_prologue_cache);
+ return (struct lm32_frame_cache *) (*this_prologue_cache);
info = FRAME_OBSTACK_ZALLOC (struct lm32_frame_cache);
(*this_prologue_cache) = info;
/* Convert callee save offsets into addresses. */
for (i = 0; i < gdbarch_num_regs (get_frame_arch (this_frame)) - 1; i++)
{
- if (trad_frame_addr_p (info->saved_regs, i))
- info->saved_regs[i].addr = this_base + info->saved_regs[i].addr;
+ if (info->saved_regs[i].is_addr ())
+ info->saved_regs[i].set_addr (this_base + info->saved_regs[i].addr ());
}
/* The call instruction moves the caller's PC in the callee's RA register.
/* The previous frame's SP needed to be computed. Save the computed
value. */
- trad_frame_set_value (info->saved_regs, SIM_LM32_SP_REGNUM, prev_sp);
+ info->saved_regs[SIM_LM32_SP_REGNUM].set_value (prev_sp);
return info;
}
static void
-lm32_frame_this_id (struct frame_info *this_frame, void **this_cache,
+lm32_frame_this_id (frame_info_ptr this_frame, void **this_cache,
struct frame_id *this_id)
{
struct lm32_frame_cache *cache = lm32_frame_cache (this_frame, this_cache);
}
static struct value *
-lm32_frame_prev_register (struct frame_info *this_frame,
+lm32_frame_prev_register (frame_info_ptr this_frame,
void **this_prologue_cache, int regnum)
{
struct lm32_frame_cache *info;
}
static const struct frame_unwind lm32_frame_unwind = {
+ "lm32 prologue",
NORMAL_FRAME,
default_frame_unwind_stop_reason,
lm32_frame_this_id,
};
static CORE_ADDR
-lm32_frame_base_address (struct frame_info *this_frame, void **this_cache)
+lm32_frame_base_address (frame_info_ptr this_frame, void **this_cache)
{
struct lm32_frame_cache *info = lm32_frame_cache (this_frame, this_cache);
static struct gdbarch *
lm32_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
{
- struct gdbarch *gdbarch;
- struct gdbarch_tdep *tdep;
-
/* If there is already a candidate, use it. */
arches = gdbarch_list_lookup_by_info (arches, &info);
if (arches != NULL)
return arches->gdbarch;
/* None found, create a new architecture from the information provided. */
- tdep = XMALLOC (struct gdbarch_tdep);
- gdbarch = gdbarch_alloc (&info, tdep);
+ gdbarch *gdbarch
+ = gdbarch_alloc (&info, gdbarch_tdep_up (new lm32_gdbarch_tdep));
/* Type sizes. */
set_gdbarch_short_bit (gdbarch, 16);
/* Frame unwinding. */
set_gdbarch_frame_align (gdbarch, lm32_frame_align);
frame_base_set_default (gdbarch, &lm32_frame_base);
- set_gdbarch_unwind_pc (gdbarch, lm32_unwind_pc);
- set_gdbarch_unwind_sp (gdbarch, lm32_unwind_sp);
- set_gdbarch_dummy_id (gdbarch, lm32_dummy_id);
frame_unwind_append_unwinder (gdbarch, &lm32_frame_unwind);
/* Breakpoints. */
- set_gdbarch_breakpoint_from_pc (gdbarch, lm32_breakpoint_from_pc);
+ set_gdbarch_breakpoint_kind_from_pc (gdbarch, lm32_breakpoint::kind_from_pc);
+ set_gdbarch_sw_breakpoint_from_kind (gdbarch, lm32_breakpoint::bp_from_kind);
set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1);
/* Calling functions in the inferior. */
set_gdbarch_push_dummy_call (gdbarch, lm32_push_dummy_call);
set_gdbarch_return_value (gdbarch, lm32_return_value);
- /* Instruction disassembler. */
- set_gdbarch_print_insn (gdbarch, print_insn_lm32);
-
- lm32_add_reggroups (gdbarch);
set_gdbarch_register_reggroup_p (gdbarch, lm32_register_reggroup_p);
return gdbarch;
}
-/* -Wmissing-prototypes */
-extern initialize_file_ftype _initialize_lm32_tdep;
-
+void _initialize_lm32_tdep ();
void
-_initialize_lm32_tdep (void)
+_initialize_lm32_tdep ()
{
- register_gdbarch_init (bfd_arch_lm32, lm32_gdbarch_init);
+ gdbarch_register (bfd_arch_lm32, lm32_gdbarch_init);
}