/* Target-dependent code for Lattice Mico32 processor, for GDB.
Contributed by Jon Beniston <jon@beniston.com>
- Copyright (C) 2009 Free Software Foundation, Inc.
+ Copyright (C) 2009-2020 Free Software Foundation, Inc.
This file is part of GDB.
#include "trad-frame.h"
#include "reggroups.h"
#include "opcodes/lm32-desc.h"
-
-#include "gdb_string.h"
+#include <algorithm>
/* Macros to extract fields from an instruction. */
#define LM32_OPCODE(insn) ((insn >> 26) & 0x3f)
struct gdbarch_tdep
{
- /* gdbarch target dependent data here. Currently unused for LM32. */
+ /* gdbarch target dependent data here. Currently unused for LM32. */
};
struct lm32_frame_cache
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",
static struct type *
lm32_register_type (struct gdbarch *gdbarch, int reg_nr)
{
- return builtin_type_int32;
+ return builtin_type (gdbarch)->builtin_int32;
}
/* Return non-zero if a register can't be written. */
/* Analyze a function's prologue. */
static CORE_ADDR
-lm32_analyze_prologue (CORE_ADDR pc, CORE_ADDR limit,
+lm32_analyze_prologue (struct gdbarch *gdbarch,
+ CORE_ADDR pc, CORE_ADDR limit,
struct lm32_frame_cache *info)
{
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
unsigned long instruction;
/* Keep reading though instructions, until we come across an instruction
{
/* Read an instruction. */
- instruction = read_memory_integer (pc, 4);
+ instruction = read_memory_integer (pc, 4, byte_order);
if ((LM32_OPCODE (instruction) == OP_SW)
&& (LM32_REG0 (instruction) == SIM_LM32_SP_REGNUM))
{
- /* Any stack displaced store is likely part of the prologue.
+ /* 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 =
else if ((LM32_OPCODE (instruction) == OP_ADDI)
&& (LM32_REG1 (instruction) == SIM_LM32_SP_REGNUM))
{
- /* An add to the SP is likely to be part of the prologue.
+ /* An add to the SP is likely to be part of the prologue.
Adjust stack size by whatever the instruction adds to the sp. */
info->size -= LM32_IMM16 (instruction);
}
}
else
{
- /* Any other instruction is likely not to be part of the prologue. */
+ /* Any other instruction is likely not to be part of the
+ prologue. */
break;
}
}
lm32_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
{
CORE_ADDR func_addr, limit_pc;
- struct symtab_and_line sal;
struct lm32_frame_cache frame_info;
struct trad_frame_saved_reg saved_regs[SIM_LM32_NUM_REGS];
is greater. */
if (find_pc_partial_function (pc, NULL, &func_addr, NULL))
{
- CORE_ADDR post_prologue_pc = skip_prologue_using_sal (func_addr);
+ 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
/* Find an upper limit on the function prologue using the debug
information. If the debug information could not be used to provide
that bound, then use an arbitrary large number as the upper bound. */
- limit_pc = skip_prologue_using_sal (pc);
+ limit_pc = skip_prologue_using_sal (gdbarch, pc);
if (limit_pc == 0)
limit_pc = pc + 100; /* Magic. */
frame_info.saved_regs = saved_regs;
- return lm32_analyze_prologue (pc, limit_pc, &frame_info);
+ return lm32_analyze_prologue (gdbarch, pc, limit_pc, &frame_info);
}
/* 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;
int num_arg_regs = 8;
int i;
/* 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++;
struct value *arg = args[i];
struct type *arg_type = check_typedef (value_type (arg));
gdb_byte *contents;
- int len;
- int j;
- int reg;
ULONGEST val;
/* Promote small integer types to int. */
case TYPE_CODE_ENUM:
if (TYPE_LENGTH (arg_type) < 4)
{
- arg_type = builtin_type_int32;
+ arg_type = builtin_type (gdbarch)->builtin_int32;
arg = value_cast (arg_type, arg);
}
break;
/* FIXME: Handle structures. */
contents = (gdb_byte *) value_contents (arg);
- len = TYPE_LENGTH (arg_type);
- val = extract_unsigned_integer (contents, len);
+ val = extract_unsigned_integer (contents, TYPE_LENGTH (arg_type),
+ byte_order);
/* First num_arg_regs parameters are passed by registers,
and the rest are passed on the stack. */
regcache_cooked_write_unsigned (regcache, first_arg_reg + i, val);
else
{
- write_memory (sp, (void *) &val, len);
+ write_memory_unsigned_integer (sp, TYPE_LENGTH (arg_type), byte_order,
+ val);
sp -= 4;
}
}
lm32_extract_return_value (struct type *type, struct regcache *regcache,
gdb_byte *valbuf)
{
- int offset;
+ struct gdbarch *gdbarch = regcache->arch ();
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
ULONGEST l;
CORE_ADDR return_buffer;
{
/* 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), l);
+ store_unsigned_integer (valbuf, TYPE_LENGTH (type), byte_order, l);
}
else if ((TYPE_CODE (type) == TYPE_CODE_INT) && (TYPE_LENGTH (type) == 8))
{
}
else
{
- /* Aggregate types greater than a single register are returned in memory.
- FIXME: Unless they are only 2 regs?. */
+ /* Aggregate types greater than a single register are returned
+ 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));
lm32_store_return_value (struct type *type, struct regcache *regcache,
const gdb_byte *valbuf)
{
+ struct gdbarch *gdbarch = regcache->arch ();
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
ULONGEST val;
int len = TYPE_LENGTH (type);
if (len <= 4)
{
- val = extract_unsigned_integer (valbuf, len);
+ val = extract_unsigned_integer (valbuf, len, byte_order);
regcache_cooked_write_unsigned (regcache, SIM_LM32_R1_REGNUM, val);
}
else if (len <= 8)
{
- val = extract_unsigned_integer (valbuf, 4);
+ val = extract_unsigned_integer (valbuf, 4, byte_order);
regcache_cooked_write_unsigned (regcache, SIM_LM32_R1_REGNUM, val);
- val = extract_unsigned_integer (valbuf + 4, len - 4);
+ val = extract_unsigned_integer (valbuf + 4, len - 4, byte_order);
regcache_cooked_write_unsigned (regcache, SIM_LM32_R2_REGNUM, val);
}
else
/* Determine whether a functions return value is in a register or memory. */
static enum return_value_convention
-lm32_return_value (struct gdbarch *gdbarch, struct type *func_type,
+lm32_return_value (struct gdbarch *gdbarch, struct value *function,
struct type *valtype, struct regcache *regcache,
gdb_byte *readbuf, const gdb_byte *writebuf)
{
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
static struct lm32_frame_cache *
lm32_frame_cache (struct frame_info *this_frame, void **this_prologue_cache)
{
- CORE_ADDR prologue_pc;
CORE_ADDR current_pc;
ULONGEST prev_sp;
ULONGEST this_base;
struct lm32_frame_cache *info;
- int prefixed;
- unsigned long instruction;
- int op;
- int offsets[32];
int i;
- long immediate;
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;
info->pc = get_frame_func (this_frame);
current_pc = get_frame_pc (this_frame);
- lm32_analyze_prologue (info->pc, current_pc, info);
+ lm32_analyze_prologue (get_frame_arch (this_frame),
+ info->pc, current_pc, info);
/* Compute the frame's base, and the previous frame's SP. */
this_base = get_frame_register_unsigned (this_frame, SIM_LM32_SP_REGNUM);
converted into a request for the RA register. */
info->saved_regs[SIM_LM32_PC_REGNUM] = info->saved_regs[SIM_LM32_RA_REGNUM];
- /* The previous frame's SP needed to be computed. Save the computed value. */
+ /* 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);
return info;
static const struct frame_unwind lm32_frame_unwind = {
NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
lm32_frame_this_id,
lm32_frame_prev_register,
NULL,
return arches->gdbarch;
/* None found, create a new architecture from the information provided. */
- tdep = XMALLOC (struct gdbarch_tdep);
+ tdep = XCNEW (struct gdbarch_tdep);
gdbarch = gdbarch_alloc (&info, tdep);
/* Type sizes. */
/* 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);