/* Common target dependent code for GDB on ARM systems.
- Copyright (C) 1988-2020 Free Software Foundation, Inc.
+ Copyright (C) 1988-2022 Free Software Foundation, Inc.
This file is part of GDB.
static bool arm_debug;
+/* Print an "arm" debug statement. */
+
+#define arm_debug_printf(fmt, ...) \
+ debug_prefixed_printf_cond (arm_debug, "arm", fmt, ##__VA_ARGS__)
+
/* Macros for setting and testing a bit in a minimal symbol that marks
it as Thumb function. The MSB of the minimal symbol's "info" field
is used for this purpose.
int framereg;
/* Saved register offsets. */
- struct trad_frame_saved_reg *saved_regs;
+ trad_frame_saved_reg *saved_regs;
};
namespace {
class arm_instruction_reader
{
public:
- /* Read a 4 bytes instruction bytes from memory using the BYTE_ORDER
- endianness. */
+ /* Read a 4 bytes instruction from memory using the BYTE_ORDER endianness. */
virtual uint32_t read (CORE_ADDR memaddr, bfd_endian byte_order) const = 0;
};
int
arm_psr_thumb_bit (struct gdbarch *gdbarch)
{
- if (gdbarch_tdep (gdbarch)->is_m)
+ arm_gdbarch_tdep *tdep = (arm_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+
+ if (tdep->is_m)
return XPSR_T;
else
return CPSR_T;
data->section_maps_sorted[section_idx] = true;
}
- struct arm_mapping_symbol map_key
- = { memaddr - obj_section_addr (sec), 0 };
+ arm_mapping_symbol map_key = { memaddr - sec->addr (), 0 };
arm_mapping_symbol_vec::const_iterator it
= std::lower_bound (map.begin (), map.end (), map_key);
if (it->value == map_key.value)
{
if (start)
- *start = it->value + obj_section_addr (sec);
+ *start = it->value + sec->addr ();
return it->type;
}
}
= it - 1;
if (start)
- *start = prev_it->value + obj_section_addr (sec);
+ *start = prev_it->value + sec->addr ();
return prev_it->type;
}
}
{
struct bound_minimal_symbol sym;
char type;
- arm_displaced_step_closure *dsc
- = ((arm_displaced_step_closure * )
- get_displaced_step_closure_by_addr (memaddr));
+ arm_displaced_step_copy_insn_closure *dsc = nullptr;
+ arm_gdbarch_tdep *tdep = (arm_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+
+ if (gdbarch_displaced_step_copy_insn_closure_by_addr_p (gdbarch))
+ dsc = ((arm_displaced_step_copy_insn_closure * )
+ gdbarch_displaced_step_copy_insn_closure_by_addr
+ (gdbarch, current_inferior (), memaddr));
/* If checking the mode of displaced instruction in copy area, the mode
should be determined by instruction on the original address. */
return 1;
/* ARM v6-M and v7-M are always in Thumb mode. */
- if (gdbarch_tdep (gdbarch)->is_m)
+ if (tdep->is_m)
return 1;
/* If there are mapping symbols, consult them. */
static CORE_ADDR
arm_addr_bits_remove (struct gdbarch *gdbarch, CORE_ADDR val)
{
+ arm_gdbarch_tdep *tdep = (arm_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+
/* On M-profile devices, do not strip the low bit from EXC_RETURN
(the magic exception return address). */
- if (gdbarch_tdep (gdbarch)->is_m
- && arm_m_addr_is_magic (val))
+ if (tdep->is_m && arm_m_addr_is_magic (val))
return val;
if (arm_apcs_32)
start += 2;
}
- if (arm_debug)
- fprintf_unfiltered (gdb_stdlog, "Prologue scan stopped at %s\n",
- paddress (gdbarch, start));
+ arm_debug_printf ("Prologue scan stopped at %s",
+ paddress (gdbarch, start));
if (unrecognized_pc == 0)
unrecognized_pc = start;
for (i = 0; i < 16; i++)
if (stack.find_reg (gdbarch, i, &offset))
- cache->saved_regs[i].addr = offset;
+ cache->saved_regs[i].set_addr (offset);
return unrecognized_pc;
}
missing (e.g. for -gstabs), assuming the GNU tools. */
if (post_prologue_pc
&& (cust == NULL
- || COMPUNIT_PRODUCER (cust) == NULL
- || startswith (COMPUNIT_PRODUCER (cust), "GNU ")
- || producer_is_llvm (COMPUNIT_PRODUCER (cust))))
+ || cust->producer () == NULL
+ || startswith (cust->producer (), "GNU ")
+ || producer_is_llvm (cust->producer ())))
return post_prologue_pc;
if (post_prologue_pc != 0)
CORE_ADDR offset, current_pc;
pv_t regs[ARM_FPS_REGNUM];
CORE_ADDR unrecognized_pc = 0;
+ arm_gdbarch_tdep *tdep = (arm_gdbarch_tdep *) gdbarch_tdep (gdbarch);
/* Search the prologue looking for instructions that set up the
frame pointer, adjust the stack pointer, and save registers.
}
else if ((insn & 0xffff7fff) == 0xed6d0103 /* stfe f?,
[sp, -#c]! */
- && gdbarch_tdep (gdbarch)->have_fpa_registers)
+ && tdep->have_fpa_registers)
{
if (stack.store_would_trash (regs[ARM_SP_REGNUM]))
break;
}
else if ((insn & 0xffbf0fff) == 0xec2d0200 /* sfmfd f0, 4,
[sp!] */
- && gdbarch_tdep (gdbarch)->have_fpa_registers)
+ && tdep->have_fpa_registers)
{
int n_saved_fp_regs;
unsigned int fp_start_reg, fp_bound_reg;
for (regno = 0; regno < ARM_FPS_REGNUM; regno++)
if (stack.find_reg (gdbarch, regno, &offset))
- cache->saved_regs[regno].addr = offset;
+ cache->saved_regs[regno].set_addr (offset);
}
- if (arm_debug)
- fprintf_unfiltered (gdb_stdlog, "Prologue scan stopped at %s\n",
- paddress (gdbarch, unrecognized_pc));
+ arm_debug_printf ("Prologue scan stopped at %s",
+ paddress (gdbarch, unrecognized_pc));
return unrecognized_pc;
}
CORE_ADDR prologue_start, prologue_end;
CORE_ADDR prev_pc = get_frame_pc (this_frame);
CORE_ADDR block_addr = get_frame_address_in_block (this_frame);
+ arm_gdbarch_tdep *tdep = (arm_gdbarch_tdep *) gdbarch_tdep (gdbarch);
/* Assume there is no frame until proven otherwise. */
cache->framereg = ARM_SP_REGNUM;
ULONGEST return_value;
/* AAPCS does not use a frame register, so we can abort here. */
- if (gdbarch_tdep (gdbarch)->arm_abi == ARM_ABI_AAPCS)
+ if (tdep->arm_abi == ARM_ABI_AAPCS)
return;
frame_loc = get_frame_register_unsigned (this_frame, ARM_FP_REGNUM);
/* Calculate actual addresses of saved registers using offsets
determined by arm_scan_prologue. */
for (reg = 0; reg < gdbarch_num_regs (get_frame_arch (this_frame)); reg++)
- if (trad_frame_addr_p (cache->saved_regs, reg))
- cache->saved_regs[reg].addr += cache->prev_sp;
+ if (cache->saved_regs[reg].is_addr ())
+ cache->saved_regs[reg].set_addr (cache->saved_regs[reg].addr ()
+ + cache->prev_sp);
return cache;
}
/* This is meant to halt the backtrace at "_start". */
pc = get_frame_pc (this_frame);
- if (pc <= gdbarch_tdep (get_frame_arch (this_frame))->lowest_pc)
+ gdbarch *arch = get_frame_arch (this_frame);
+ arm_gdbarch_tdep *tdep = (arm_gdbarch_tdep *) gdbarch_tdep (arch);
+ if (pc <= tdep->lowest_pc)
return UNWIND_OUTERMOST;
/* If we've hit a wall, stop. */
prev_regnum);
}
-struct frame_unwind arm_prologue_unwind = {
+static frame_unwind arm_prologue_unwind = {
+ "arm prologue",
NORMAL_FRAME,
arm_prologue_unwind_stop_reason,
arm_prologue_this_id,
NULL
};
- CORE_ADDR pc = pers + obj_section_offset (pers_sec);
+ CORE_ADDR pc = pers + pers_sec->offset ();
int k;
for (k = 0; personality[k]; k++)
if (sec != NULL)
{
struct arm_exidx_data *data;
- struct arm_exidx_entry map_key = { memaddr - obj_section_addr (sec), 0 };
+ struct arm_exidx_entry map_key = { memaddr - sec->addr (), 0 };
data = arm_exidx_data_key.get (sec->objfile->obfd);
if (data != NULL)
if (idx->addr == map_key.addr)
{
if (start)
- *start = idx->addr + obj_section_addr (sec);
+ *start = idx->addr + sec->addr ();
return idx->entry;
}
}
{
idx = idx - 1;
if (start)
- *start = idx->addr + obj_section_addr (sec);
+ *start = idx->addr + sec->addr ();
return idx->entry;
}
}
actual value in the current frame. */
if (!vsp_valid)
{
- if (trad_frame_realreg_p (cache->saved_regs, ARM_SP_REGNUM))
+ if (cache->saved_regs[ARM_SP_REGNUM].is_realreg ())
{
- int reg = cache->saved_regs[ARM_SP_REGNUM].realreg;
+ int reg = cache->saved_regs[ARM_SP_REGNUM].realreg ();
vsp = get_frame_register_unsigned (this_frame, reg);
}
else
{
- CORE_ADDR addr = cache->saved_regs[ARM_SP_REGNUM].addr;
+ CORE_ADDR addr = cache->saved_regs[ARM_SP_REGNUM].addr ();
vsp = get_frame_memory_unsigned (this_frame, addr, 4);
}
for (i = 0; i < 12; i++)
if (mask & (1 << i))
{
- cache->saved_regs[4 + i].addr = vsp;
+ cache->saved_regs[4 + i].set_addr (vsp);
vsp += 4;
}
/* Pop r4..r[4+count]. */
for (i = 0; i <= count; i++)
{
- cache->saved_regs[4 + i].addr = vsp;
+ cache->saved_regs[4 + i].set_addr (vsp);
vsp += 4;
}
/* If indicated by flag, pop LR as well. */
if (pop_lr)
{
- cache->saved_regs[ARM_LR_REGNUM].addr = vsp;
+ cache->saved_regs[ARM_LR_REGNUM].set_addr (vsp);
vsp += 4;
}
}
{
/* We could only have updated PC by popping into it; if so, it
will show up as address. Otherwise, copy LR into PC. */
- if (!trad_frame_addr_p (cache->saved_regs, ARM_PC_REGNUM))
+ if (!cache->saved_regs[ARM_PC_REGNUM].is_addr ())
cache->saved_regs[ARM_PC_REGNUM]
= cache->saved_regs[ARM_LR_REGNUM];
for (i = 0; i < 4; i++)
if (mask & (1 << i))
{
- cache->saved_regs[i].addr = vsp;
+ cache->saved_regs[i].set_addr (vsp);
vsp += 4;
}
}
/* Pop VFP double-precision registers D[start]..D[start+count]. */
for (i = 0; i <= count; i++)
{
- cache->saved_regs[ARM_D0_REGNUM + start + i].addr = vsp;
+ cache->saved_regs[ARM_D0_REGNUM + start + i].set_addr (vsp);
vsp += 8;
}
/* Pop VFP double-precision registers D[8]..D[8+count]. */
for (i = 0; i <= count; i++)
{
- cache->saved_regs[ARM_D0_REGNUM + 8 + i].addr = vsp;
+ cache->saved_regs[ARM_D0_REGNUM + 8 + i].set_addr (vsp);
vsp += 8;
}
/* Pop iwmmx registers WR[start]..WR[start+count]. */
for (i = 0; i <= count; i++)
{
- cache->saved_regs[ARM_WR0_REGNUM + start + i].addr = vsp;
+ cache->saved_regs[ARM_WR0_REGNUM + start + i].set_addr (vsp);
vsp += 8;
}
}
for (i = 0; i < 4; i++)
if (mask & (1 << i))
{
- cache->saved_regs[ARM_WCGR0_REGNUM + i].addr = vsp;
+ cache->saved_regs[ARM_WCGR0_REGNUM + i].set_addr (vsp);
vsp += 4;
}
}
/* Pop iwmmx registers WR[10]..WR[10+count]. */
for (i = 0; i <= count; i++)
{
- cache->saved_regs[ARM_WR0_REGNUM + 10 + i].addr = vsp;
+ cache->saved_regs[ARM_WR0_REGNUM + 10 + i].set_addr (vsp);
vsp += 8;
}
}
D[16+start]..D[16+start+count]. */
for (i = 0; i <= count; i++)
{
- cache->saved_regs[ARM_D0_REGNUM + 16 + start + i].addr = vsp;
+ cache->saved_regs[ARM_D0_REGNUM + 16 + start + i].set_addr (vsp);
vsp += 8;
}
}
/* Pop VFP double-precision registers D[start]..D[start+count]. */
for (i = 0; i <= count; i++)
{
- cache->saved_regs[ARM_D0_REGNUM + start + i].addr = vsp;
+ cache->saved_regs[ARM_D0_REGNUM + start + i].set_addr (vsp);
vsp += 8;
}
}
/* Pop VFP double-precision registers D[8]..D[8+count]. */
for (i = 0; i <= count; i++)
{
- cache->saved_regs[ARM_D0_REGNUM + 8 + i].addr = vsp;
+ cache->saved_regs[ARM_D0_REGNUM + 8 + i].set_addr (vsp);
vsp += 8;
}
}
/* If we restore SP from a register, assume this was the frame register.
Otherwise just fall back to SP as frame register. */
- if (trad_frame_realreg_p (cache->saved_regs, ARM_SP_REGNUM))
- cache->framereg = cache->saved_regs[ARM_SP_REGNUM].realreg;
+ if (cache->saved_regs[ARM_SP_REGNUM].is_realreg ())
+ cache->framereg = cache->saved_regs[ARM_SP_REGNUM].realreg ();
else
cache->framereg = ARM_SP_REGNUM;
}
struct frame_unwind arm_exidx_unwind = {
+ "arm exidx",
NORMAL_FRAME,
default_frame_unwind_stop_reason,
arm_prologue_this_id,
/* Calculate actual addresses of saved registers using offsets
determined by arm_scan_prologue. */
for (reg = 0; reg < gdbarch_num_regs (get_frame_arch (this_frame)); reg++)
- if (trad_frame_addr_p (cache->saved_regs, reg))
- cache->saved_regs[reg].addr += cache->prev_sp;
+ if (cache->saved_regs[reg].is_addr ())
+ cache->saved_regs[reg].set_addr (cache->saved_regs[reg].addr ()
+ + cache->prev_sp);
return cache;
}
static const struct frame_unwind arm_epilogue_frame_unwind =
{
+ "arm epilogue",
NORMAL_FRAME,
default_frame_unwind_stop_reason,
arm_epilogue_frame_this_id,
}
struct frame_unwind arm_stub_unwind = {
+ "arm stub",
NORMAL_FRAME,
default_frame_unwind_stop_reason,
arm_stub_this_id,
ReturnAddress, LR (R14), R12, R3, R2, R1, R0. See details in
"B1.5.6 Exception entry behavior" in
"ARMv7-M Architecture Reference Manual". */
- cache->saved_regs[0].addr = unwound_sp;
- cache->saved_regs[1].addr = unwound_sp + 4;
- cache->saved_regs[2].addr = unwound_sp + 8;
- cache->saved_regs[3].addr = unwound_sp + 12;
- cache->saved_regs[ARM_IP_REGNUM].addr = unwound_sp + 16;
- cache->saved_regs[ARM_LR_REGNUM].addr = unwound_sp + 20;
- cache->saved_regs[ARM_PC_REGNUM].addr = unwound_sp + 24;
- cache->saved_regs[ARM_PS_REGNUM].addr = unwound_sp + 28;
+ cache->saved_regs[0].set_addr (unwound_sp);
+ cache->saved_regs[1].set_addr (unwound_sp + 4);
+ cache->saved_regs[2].set_addr (unwound_sp + 8);
+ cache->saved_regs[3].set_addr (unwound_sp + 12);
+ cache->saved_regs[ARM_IP_REGNUM].set_addr (unwound_sp + 16);
+ cache->saved_regs[ARM_LR_REGNUM].set_addr (unwound_sp + 20);
+ cache->saved_regs[ARM_PC_REGNUM].set_addr (unwound_sp + 24);
+ cache->saved_regs[ARM_PS_REGNUM].set_addr (unwound_sp + 28);
/* Check EXC_RETURN bit FTYPE if extended stack frame (FPU regs stored)
type used. */
fpu_regs_stack_offset = unwound_sp + 0x20;
for (i = 0; i < 16; i++)
{
- cache->saved_regs[ARM_D0_REGNUM + i].addr = fpu_regs_stack_offset;
+ cache->saved_regs[ARM_D0_REGNUM + i].set_addr (fpu_regs_stack_offset);
fpu_regs_stack_offset += 4;
}
- cache->saved_regs[ARM_FPSCR_REGNUM].addr = unwound_sp + 0x60;
+ cache->saved_regs[ARM_FPSCR_REGNUM].set_addr (unwound_sp + 0x60);
/* Offset 0x64 is reserved. */
cache->prev_sp = unwound_sp + 0x68;
struct frame_unwind arm_m_exception_unwind =
{
+ "arm m exception",
SIGTRAMP_FRAME,
default_frame_unwind_stop_reason,
arm_m_exception_this_id,
static int
arm_vfp_abi_for_function (struct gdbarch *gdbarch, struct type *func_type)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ arm_gdbarch_tdep *tdep = (arm_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+
/* Variadic functions always use the base ABI. Assume that functions
without debug info are not variadic. */
if (func_type && check_typedef (func_type)->has_varargs ())
return 0;
+
/* The VFP ABI is only supported as a variant of AAPCS. */
if (tdep->arm_abi != ARM_ABI_AAPCS)
return 0;
- return gdbarch_tdep (gdbarch)->fp_model == ARM_FLOAT_VFP;
+
+ return tdep->fp_model == ARM_FLOAT_VFP;
}
/* We currently only support passing parameters in integer registers, which
int use_vfp_abi;
struct type *ftype;
unsigned vfp_regs_free = (1 << 16) - 1;
+ arm_gdbarch_tdep *tdep = (arm_gdbarch_tdep *) gdbarch_tdep (gdbarch);
/* Determine the type of this function and whether the VFP ABI
applies. */
passing register. */
if (return_method == return_method_struct)
{
- if (arm_debug)
- fprintf_unfiltered (gdb_stdlog, "struct return in %s = %s\n",
- gdbarch_register_name (gdbarch, argreg),
- paddress (gdbarch, struct_addr));
+ arm_debug_printf ("struct return in %s = %s",
+ gdbarch_register_name (gdbarch, argreg),
+ paddress (gdbarch, struct_addr));
+
regcache_cooked_write_unsigned (regcache, argreg, struct_addr);
argreg++;
}
len = TYPE_LENGTH (arg_type);
target_type = TYPE_TARGET_TYPE (arg_type);
typecode = arg_type->code ();
- val = value_contents (args[argnum]);
+ val = value_contents (args[argnum]).data ();
align = type_align (arg_type);
/* Round alignment up to a whole number of words. */
align = (align + ARM_INT_REGISTER_SIZE - 1)
& ~(ARM_INT_REGISTER_SIZE - 1);
/* Different ABIs have different maximum alignments. */
- if (gdbarch_tdep (gdbarch)->arm_abi == ARM_ABI_APCS)
+ if (tdep->arm_abi == ARM_ABI_APCS)
{
/* The APCS ABI only requires word alignment. */
align = ARM_INT_REGISTER_SIZE;
register. */
if (byte_order == BFD_ENDIAN_BIG)
regval <<= (ARM_INT_REGISTER_SIZE - partial_len) * 8;
- if (arm_debug)
- fprintf_unfiltered (gdb_stdlog, "arg %d in %s = 0x%s\n",
- argnum,
- gdbarch_register_name
- (gdbarch, argreg),
- phex (regval, ARM_INT_REGISTER_SIZE));
+
+ arm_debug_printf ("arg %d in %s = 0x%s", argnum,
+ gdbarch_register_name (gdbarch, argreg),
+ phex (regval, ARM_INT_REGISTER_SIZE));
+
regcache_cooked_write_unsigned (regcache, argreg, regval);
argreg++;
}
store_unsigned_integer (buf, partial_len, byte_order, regval);
/* Push the arguments onto the stack. */
- if (arm_debug)
- fprintf_unfiltered (gdb_stdlog, "arg %d @ sp + %d\n",
- argnum, nstack);
+ arm_debug_printf ("arg %d @ sp + %d", argnum, nstack);
si = push_stack_item (si, buf, ARM_INT_REGISTER_SIZE);
nstack += ARM_INT_REGISTER_SIZE;
}
print_fpu_flags (struct ui_file *file, int flags)
{
if (flags & (1 << 0))
- fputs_filtered ("IVO ", file);
+ gdb_puts ("IVO ", file);
if (flags & (1 << 1))
- fputs_filtered ("DVZ ", file);
+ gdb_puts ("DVZ ", file);
if (flags & (1 << 2))
- fputs_filtered ("OFL ", file);
+ gdb_puts ("OFL ", file);
if (flags & (1 << 3))
- fputs_filtered ("UFL ", file);
+ gdb_puts ("UFL ", file);
if (flags & (1 << 4))
- fputs_filtered ("INX ", file);
- fputc_filtered ('\n', file);
+ gdb_puts ("INX ", file);
+ gdb_putc ('\n', file);
}
/* Print interesting information about the floating point processor
type = (status >> 24) & 127;
if (status & (1 << 31))
- fprintf_filtered (file, _("Hardware FPU type %d\n"), type);
+ gdb_printf (file, _("Hardware FPU type %d\n"), type);
else
- fprintf_filtered (file, _("Software FPU type %d\n"), type);
+ gdb_printf (file, _("Software FPU type %d\n"), type);
/* i18n: [floating point unit] mask */
- fputs_filtered (_("mask: "), file);
+ gdb_puts (_("mask: "), file);
print_fpu_flags (file, status >> 16);
/* i18n: [floating point unit] flags */
- fputs_filtered (_("flags: "), file);
+ gdb_puts (_("flags: "), file);
print_fpu_flags (file, status);
}
static struct type *
arm_ext_type (struct gdbarch *gdbarch)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ arm_gdbarch_tdep *tdep = (arm_gdbarch_tdep *) gdbarch_tdep (gdbarch);
if (!tdep->arm_ext_type)
tdep->arm_ext_type
static struct type *
arm_neon_double_type (struct gdbarch *gdbarch)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ arm_gdbarch_tdep *tdep = (arm_gdbarch_tdep *) gdbarch_tdep (gdbarch);
if (tdep->neon_double_type == NULL)
{
static struct type *
arm_neon_quad_type (struct gdbarch *gdbarch)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ arm_gdbarch_tdep *tdep = (arm_gdbarch_tdep *) gdbarch_tdep (gdbarch);
if (tdep->neon_quad_type == NULL)
{
return tdep->neon_quad_type;
}
+/* Return true if REGNUM is a Q pseudo register. Return false
+ otherwise.
+
+ REGNUM is the raw register number and not a pseudo-relative register
+ number. */
+
+static bool
+is_q_pseudo (struct gdbarch *gdbarch, int regnum)
+{
+ arm_gdbarch_tdep *tdep = (arm_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+
+ /* Q pseudo registers are available for both NEON (Q0~Q15) and
+ MVE (Q0~Q7) features. */
+ if (tdep->have_q_pseudos
+ && regnum >= tdep->q_pseudo_base
+ && regnum < (tdep->q_pseudo_base + tdep->q_pseudo_count))
+ return true;
+
+ return false;
+}
+
+/* Return true if REGNUM is a VFP S pseudo register. Return false
+ otherwise.
+
+ REGNUM is the raw register number and not a pseudo-relative register
+ number. */
+
+static bool
+is_s_pseudo (struct gdbarch *gdbarch, int regnum)
+{
+ arm_gdbarch_tdep *tdep = (arm_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+
+ if (tdep->have_s_pseudos
+ && regnum >= tdep->s_pseudo_base
+ && regnum < (tdep->s_pseudo_base + tdep->s_pseudo_count))
+ return true;
+
+ return false;
+}
+
+/* Return true if REGNUM is a MVE pseudo register (P0). Return false
+ otherwise.
+
+ REGNUM is the raw register number and not a pseudo-relative register
+ number. */
+
+static bool
+is_mve_pseudo (struct gdbarch *gdbarch, int regnum)
+{
+ arm_gdbarch_tdep *tdep = (arm_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+
+ if (tdep->have_mve
+ && regnum >= tdep->mve_pseudo_base
+ && regnum < tdep->mve_pseudo_base + tdep->mve_pseudo_count)
+ return true;
+
+ return false;
+}
+
/* Return the GDB type object for the "standard" data type of data in
register N. */
static struct type *
arm_register_type (struct gdbarch *gdbarch, int regnum)
{
- int num_regs = gdbarch_num_regs (gdbarch);
+ arm_gdbarch_tdep *tdep = (arm_gdbarch_tdep *) gdbarch_tdep (gdbarch);
- if (gdbarch_tdep (gdbarch)->have_vfp_pseudos
- && regnum >= num_regs && regnum < num_regs + 32)
+ if (is_s_pseudo (gdbarch, regnum))
return builtin_type (gdbarch)->builtin_float;
- if (gdbarch_tdep (gdbarch)->have_neon_pseudos
- && regnum >= num_regs + 32 && regnum < num_regs + 32 + 16)
+ if (is_q_pseudo (gdbarch, regnum))
return arm_neon_quad_type (gdbarch);
+ if (is_mve_pseudo (gdbarch, regnum))
+ return builtin_type (gdbarch)->builtin_int16;
+
/* If the target description has register information, we are only
in this function so that we can override the types of
double-precision registers for NEON. */
if (regnum >= ARM_D0_REGNUM && regnum < ARM_D0_REGNUM + 32
&& t->code () == TYPE_CODE_FLT
- && gdbarch_tdep (gdbarch)->have_neon)
+ && tdep->have_neon)
return arm_neon_double_type (gdbarch);
else
return t;
if (regnum >= ARM_F0_REGNUM && regnum < ARM_F0_REGNUM + NUM_FREGS)
{
- if (!gdbarch_tdep (gdbarch)->have_fpa_registers)
+ if (!tdep->have_fpa_registers)
return builtin_type (gdbarch)->builtin_void;
return arm_ext_type (gdbarch);
int buf_len;
enum bfd_endian order = gdbarch_byte_order_for_code (gdbarch);
int i, any, last_it, last_it_count;
+ arm_gdbarch_tdep *tdep = (arm_gdbarch_tdep *) gdbarch_tdep (gdbarch);
/* If we are using BKPT breakpoints, none of this is necessary. */
- if (gdbarch_tdep (gdbarch)->thumb2_breakpoint == NULL)
+ if (tdep->thumb2_breakpoint == NULL)
return bpaddr;
/* ARM mode does not have this problem. */
location. */
ULONGEST
-displaced_read_reg (struct regcache *regs, arm_displaced_step_closure *dsc,
+displaced_read_reg (regcache *regs, arm_displaced_step_copy_insn_closure *dsc,
int regno)
{
ULONGEST ret;
/* Write to the PC as from a branch instruction. */
static void
-branch_write_pc (struct regcache *regs, arm_displaced_step_closure *dsc,
+branch_write_pc (regcache *regs, arm_displaced_step_copy_insn_closure *dsc,
ULONGEST val)
{
if (!dsc->is_thumb)
/* Write to the PC as if from a load instruction. */
static void
-load_write_pc (struct regcache *regs, arm_displaced_step_closure *dsc,
+load_write_pc (regcache *regs, arm_displaced_step_copy_insn_closure *dsc,
ULONGEST val)
{
if (DISPLACED_STEPPING_ARCH_VERSION >= 5)
/* Write to the PC as if from an ALU instruction. */
static void
-alu_write_pc (struct regcache *regs, arm_displaced_step_closure *dsc,
+alu_write_pc (regcache *regs, arm_displaced_step_copy_insn_closure *dsc,
ULONGEST val)
{
if (DISPLACED_STEPPING_ARCH_VERSION >= 7 && !dsc->is_thumb)
this is controlled by the WRITE_PC argument. */
void
-displaced_write_reg (struct regcache *regs, arm_displaced_step_closure *dsc,
+displaced_write_reg (regcache *regs, arm_displaced_step_copy_insn_closure *dsc,
int regno, ULONGEST val, enum pc_write_style write_pc)
{
if (regno == ARM_PC_REGNUM)
case BX_WRITE_PC:
bx_write_pc (regs, val);
- break;
+ break;
case LOAD_WRITE_PC:
load_write_pc (regs, dsc, val);
- break;
+ break;
case ALU_WRITE_PC:
alu_write_pc (regs, dsc, val);
- break;
+ break;
case CANNOT_WRITE_PC:
warning (_("Instruction wrote to PC in an unexpected way when "
matter what address they are executed at: in those cases, use this. */
static int
-arm_copy_unmodified (struct gdbarch *gdbarch, uint32_t insn,
- const char *iname, arm_displaced_step_closure *dsc)
+arm_copy_unmodified (struct gdbarch *gdbarch, uint32_t insn, const char *iname,
+ arm_displaced_step_copy_insn_closure *dsc)
{
displaced_debug_printf ("copying insn %.8lx, opcode/class '%s' unmodified",
(unsigned long) insn, iname);
static int
thumb_copy_unmodified_32bit (struct gdbarch *gdbarch, uint16_t insn1,
uint16_t insn2, const char *iname,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
displaced_debug_printf ("copying insn %.4x %.4x, opcode/class '%s' "
"unmodified", insn1, insn2, iname);
static int
thumb_copy_unmodified_16bit (struct gdbarch *gdbarch, uint16_t insn,
const char *iname,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
displaced_debug_printf ("copying insn %.4x, opcode/class '%s' unmodified",
insn, iname);
/* Preload instructions with immediate offset. */
static void
-cleanup_preload (struct gdbarch *gdbarch,
- struct regcache *regs, arm_displaced_step_closure *dsc)
+cleanup_preload (struct gdbarch *gdbarch, regcache *regs,
+ arm_displaced_step_copy_insn_closure *dsc)
{
displaced_write_reg (regs, dsc, 0, dsc->tmp[0], CANNOT_WRITE_PC);
if (!dsc->u.preload.immed)
static void
install_preload (struct gdbarch *gdbarch, struct regcache *regs,
- arm_displaced_step_closure *dsc, unsigned int rn)
+ arm_displaced_step_copy_insn_closure *dsc, unsigned int rn)
{
ULONGEST rn_val;
/* Preload instructions:
static int
arm_copy_preload (struct gdbarch *gdbarch, uint32_t insn, struct regcache *regs,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
unsigned int rn = bits (insn, 16, 19);
static int
thumb2_copy_preload (struct gdbarch *gdbarch, uint16_t insn1, uint16_t insn2,
- struct regcache *regs, arm_displaced_step_closure *dsc)
+ regcache *regs, arm_displaced_step_copy_insn_closure *dsc)
{
unsigned int rn = bits (insn1, 0, 3);
unsigned int u_bit = bit (insn1, 7);
static void
install_preload_reg(struct gdbarch *gdbarch, struct regcache *regs,
- arm_displaced_step_closure *dsc, unsigned int rn,
+ arm_displaced_step_copy_insn_closure *dsc, unsigned int rn,
unsigned int rm)
{
ULONGEST rn_val, rm_val;
static int
arm_copy_preload_reg (struct gdbarch *gdbarch, uint32_t insn,
struct regcache *regs,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
unsigned int rn = bits (insn, 16, 19);
unsigned int rm = bits (insn, 0, 3);
static void
cleanup_copro_load_store (struct gdbarch *gdbarch,
struct regcache *regs,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
ULONGEST rn_val = displaced_read_reg (regs, dsc, 0);
static void
install_copro_load_store (struct gdbarch *gdbarch, struct regcache *regs,
- arm_displaced_step_closure *dsc,
+ arm_displaced_step_copy_insn_closure *dsc,
int writeback, unsigned int rn)
{
ULONGEST rn_val;
static int
arm_copy_copro_load_store (struct gdbarch *gdbarch, uint32_t insn,
struct regcache *regs,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
unsigned int rn = bits (insn, 16, 19);
static int
thumb2_copy_copro_load_store (struct gdbarch *gdbarch, uint16_t insn1,
uint16_t insn2, struct regcache *regs,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
unsigned int rn = bits (insn1, 0, 3);
static void
cleanup_branch (struct gdbarch *gdbarch, struct regcache *regs,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
uint32_t status = displaced_read_reg (regs, dsc, ARM_PS_REGNUM);
int branch_taken = condition_true (dsc->u.branch.cond, status);
static void
install_b_bl_blx (struct gdbarch *gdbarch, struct regcache *regs,
- arm_displaced_step_closure *dsc,
+ arm_displaced_step_copy_insn_closure *dsc,
unsigned int cond, int exchange, int link, long offset)
{
/* Implement "BL<cond> <label>" as:
}
static int
arm_copy_b_bl_blx (struct gdbarch *gdbarch, uint32_t insn,
- struct regcache *regs, arm_displaced_step_closure *dsc)
+ regcache *regs, arm_displaced_step_copy_insn_closure *dsc)
{
unsigned int cond = bits (insn, 28, 31);
int exchange = (cond == 0xf);
static int
thumb2_copy_b_bl_blx (struct gdbarch *gdbarch, uint16_t insn1,
uint16_t insn2, struct regcache *regs,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
int link = bit (insn2, 14);
int exchange = link && !bit (insn2, 12);
/* Copy B Thumb instructions. */
static int
thumb_copy_b (struct gdbarch *gdbarch, uint16_t insn,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
unsigned int cond = 0;
int offset = 0;
static void
install_bx_blx_reg (struct gdbarch *gdbarch, struct regcache *regs,
- arm_displaced_step_closure *dsc, int link,
+ arm_displaced_step_copy_insn_closure *dsc, int link,
unsigned int cond, unsigned int rm)
{
/* Implement {BX,BLX}<cond> <reg>" as:
static int
arm_copy_bx_blx_reg (struct gdbarch *gdbarch, uint32_t insn,
- struct regcache *regs, arm_displaced_step_closure *dsc)
+ regcache *regs, arm_displaced_step_copy_insn_closure *dsc)
{
unsigned int cond = bits (insn, 28, 31);
/* BX: x12xxx1x
static int
thumb_copy_bx_blx_reg (struct gdbarch *gdbarch, uint16_t insn,
struct regcache *regs,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
int link = bit (insn, 7);
unsigned int rm = bits (insn, 3, 6);
static void
cleanup_alu_imm (struct gdbarch *gdbarch,
- struct regcache *regs, arm_displaced_step_closure *dsc)
+ regcache *regs, arm_displaced_step_copy_insn_closure *dsc)
{
ULONGEST rd_val = displaced_read_reg (regs, dsc, 0);
displaced_write_reg (regs, dsc, 0, dsc->tmp[0], CANNOT_WRITE_PC);
static int
arm_copy_alu_imm (struct gdbarch *gdbarch, uint32_t insn, struct regcache *regs,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
unsigned int rn = bits (insn, 16, 19);
unsigned int rd = bits (insn, 12, 15);
static int
thumb2_copy_alu_imm (struct gdbarch *gdbarch, uint16_t insn1,
uint16_t insn2, struct regcache *regs,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
unsigned int op = bits (insn1, 5, 8);
unsigned int rn, rm, rd;
static void
cleanup_alu_reg (struct gdbarch *gdbarch,
- struct regcache *regs, arm_displaced_step_closure *dsc)
+ regcache *regs, arm_displaced_step_copy_insn_closure *dsc)
{
ULONGEST rd_val;
int i;
static void
install_alu_reg (struct gdbarch *gdbarch, struct regcache *regs,
- arm_displaced_step_closure *dsc,
+ arm_displaced_step_copy_insn_closure *dsc,
unsigned int rd, unsigned int rn, unsigned int rm)
{
ULONGEST rd_val, rn_val, rm_val;
static int
arm_copy_alu_reg (struct gdbarch *gdbarch, uint32_t insn, struct regcache *regs,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
unsigned int op = bits (insn, 21, 24);
int is_mov = (op == 0xd);
static int
thumb_copy_alu_reg (struct gdbarch *gdbarch, uint16_t insn,
struct regcache *regs,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
unsigned rm, rd;
static void
cleanup_alu_shifted_reg (struct gdbarch *gdbarch,
struct regcache *regs,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
ULONGEST rd_val = displaced_read_reg (regs, dsc, 0);
int i;
static void
install_alu_shifted_reg (struct gdbarch *gdbarch, struct regcache *regs,
- arm_displaced_step_closure *dsc,
+ arm_displaced_step_copy_insn_closure *dsc,
unsigned int rd, unsigned int rn, unsigned int rm,
unsigned rs)
{
static int
arm_copy_alu_shifted_reg (struct gdbarch *gdbarch, uint32_t insn,
struct regcache *regs,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
unsigned int op = bits (insn, 21, 24);
int is_mov = (op == 0xd);
static void
cleanup_load (struct gdbarch *gdbarch, struct regcache *regs,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
ULONGEST rt_val, rt_val2 = 0, rn_val;
static void
cleanup_store (struct gdbarch *gdbarch, struct regcache *regs,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
ULONGEST rn_val = displaced_read_reg (regs, dsc, 2);
static int
arm_copy_extra_ld_st (struct gdbarch *gdbarch, uint32_t insn, int unprivileged,
- struct regcache *regs, arm_displaced_step_closure *dsc)
+ regcache *regs, arm_displaced_step_copy_insn_closure *dsc)
{
unsigned int op1 = bits (insn, 20, 24);
unsigned int op2 = bits (insn, 5, 6);
static void
install_load_store (struct gdbarch *gdbarch, struct regcache *regs,
- arm_displaced_step_closure *dsc, int load,
+ arm_displaced_step_copy_insn_closure *dsc, int load,
int immed, int writeback, int size, int usermode,
int rt, int rm, int rn)
{
static int
thumb2_copy_load_literal (struct gdbarch *gdbarch, uint16_t insn1,
uint16_t insn2, struct regcache *regs,
- arm_displaced_step_closure *dsc, int size)
+ arm_displaced_step_copy_insn_closure *dsc, int size)
{
unsigned int u_bit = bit (insn1, 7);
unsigned int rt = bits (insn2, 12, 15);
static int
thumb2_copy_load_reg_imm (struct gdbarch *gdbarch, uint16_t insn1,
uint16_t insn2, struct regcache *regs,
- arm_displaced_step_closure *dsc,
+ arm_displaced_step_copy_insn_closure *dsc,
int writeback, int immed)
{
unsigned int rt = bits (insn2, 12, 15);
static int
arm_copy_ldr_str_ldrb_strb (struct gdbarch *gdbarch, uint32_t insn,
struct regcache *regs,
- arm_displaced_step_closure *dsc,
+ arm_displaced_step_copy_insn_closure *dsc,
int load, int size, int usermode)
{
int immed = !bit (insn, 25);
static void
cleanup_block_load_all (struct gdbarch *gdbarch, struct regcache *regs,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
int inc = dsc->u.block.increment;
int bump_before = dsc->u.block.before ? (inc ? 4 : -4) : 0;
static void
cleanup_block_store_pc (struct gdbarch *gdbarch, struct regcache *regs,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
uint32_t status = displaced_read_reg (regs, dsc, ARM_PS_REGNUM);
int store_executed = condition_true (dsc->u.block.cond, status);
static void
cleanup_block_load_pc (struct gdbarch *gdbarch,
struct regcache *regs,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
uint32_t status = displaced_read_reg (regs, dsc, ARM_PS_REGNUM);
int load_executed = condition_true (dsc->u.block.cond, status);
static int
arm_copy_block_xfer (struct gdbarch *gdbarch, uint32_t insn,
struct regcache *regs,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
int load = bit (insn, 20);
int user = bit (insn, 22);
static int
thumb2_copy_block_xfer (struct gdbarch *gdbarch, uint16_t insn1, uint16_t insn2,
struct regcache *regs,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
int rn = bits (insn1, 0, 3);
int load = bit (insn1, 4);
static void
cleanup_svc (struct gdbarch *gdbarch, struct regcache *regs,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
CORE_ADDR resume_addr = dsc->insn_addr + dsc->insn_size;
static int
install_svc (struct gdbarch *gdbarch, struct regcache *regs,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
/* Preparation: none.
Insn: unmodified svc.
static int
arm_copy_svc (struct gdbarch *gdbarch, uint32_t insn,
- struct regcache *regs, arm_displaced_step_closure *dsc)
+ regcache *regs, arm_displaced_step_copy_insn_closure *dsc)
{
displaced_debug_printf ("copying svc insn %.8lx",
static int
thumb_copy_svc (struct gdbarch *gdbarch, uint16_t insn,
- struct regcache *regs, arm_displaced_step_closure *dsc)
+ regcache *regs, arm_displaced_step_copy_insn_closure *dsc)
{
displaced_debug_printf ("copying svc insn %.4x", insn);
static int
arm_copy_undef (struct gdbarch *gdbarch, uint32_t insn,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
displaced_debug_printf ("copying undefined insn %.8lx",
(unsigned long) insn);
static int
thumb_32bit_copy_undef (struct gdbarch *gdbarch, uint16_t insn1, uint16_t insn2,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
displaced_debug_printf ("copying undefined insn %.4x %.4x",
static int
arm_copy_unpred (struct gdbarch *gdbarch, uint32_t insn,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
displaced_debug_printf ("copying unpredictable insn %.8lx",
(unsigned long) insn);
static int
arm_decode_misc_memhint_neon (struct gdbarch *gdbarch, uint32_t insn,
struct regcache *regs,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
unsigned int op1 = bits (insn, 20, 26), op2 = bits (insn, 4, 7);
unsigned int rn = bits (insn, 16, 19);
static int
arm_decode_unconditional (struct gdbarch *gdbarch, uint32_t insn,
struct regcache *regs,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
if (bit (insn, 27) == 0)
return arm_decode_misc_memhint_neon (gdbarch, insn, regs, dsc);
static int
arm_decode_miscellaneous (struct gdbarch *gdbarch, uint32_t insn,
struct regcache *regs,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
unsigned int op2 = bits (insn, 4, 6);
unsigned int op = bits (insn, 21, 22);
static int
arm_decode_dp_misc (struct gdbarch *gdbarch, uint32_t insn,
struct regcache *regs,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
if (bit (insn, 25))
switch (bits (insn, 20, 24))
static int
arm_decode_ld_st_word_ubyte (struct gdbarch *gdbarch, uint32_t insn,
struct regcache *regs,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
int a = bit (insn, 25), b = bit (insn, 4);
uint32_t op1 = bits (insn, 20, 24);
static int
arm_decode_media (struct gdbarch *gdbarch, uint32_t insn,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
switch (bits (insn, 20, 24))
{
static int
arm_decode_b_bl_ldmstm (struct gdbarch *gdbarch, uint32_t insn,
struct regcache *regs,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
if (bit (insn, 25))
return arm_copy_b_bl_blx (gdbarch, insn, regs, dsc);
static int
arm_decode_ext_reg_ld_st (struct gdbarch *gdbarch, uint32_t insn,
struct regcache *regs,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
unsigned int opcode = bits (insn, 20, 24);
static int
thumb2_decode_dp_shift_reg (struct gdbarch *gdbarch, uint16_t insn1,
uint16_t insn2, struct regcache *regs,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
/* PC is only allowed to be used in instruction MOV. */
static int
thumb2_decode_ext_reg_ld_st (struct gdbarch *gdbarch, uint16_t insn1,
uint16_t insn2, struct regcache *regs,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
unsigned int opcode = bits (insn1, 4, 8);
static int
arm_decode_svc_copro (struct gdbarch *gdbarch, uint32_t insn,
- struct regcache *regs, arm_displaced_step_closure *dsc)
+ regcache *regs, arm_displaced_step_copy_insn_closure *dsc)
{
unsigned int op1 = bits (insn, 20, 25);
int op = bit (insn, 4);
static int
thumb2_decode_svc_copro (struct gdbarch *gdbarch, uint16_t insn1,
uint16_t insn2, struct regcache *regs,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
unsigned int coproc = bits (insn2, 8, 11);
unsigned int bit_5_8 = bits (insn1, 5, 8);
static void
install_pc_relative (struct gdbarch *gdbarch, struct regcache *regs,
- arm_displaced_step_closure *dsc, int rd)
+ arm_displaced_step_copy_insn_closure *dsc, int rd)
{
/* ADR Rd, #imm
static int
thumb_copy_pc_relative_16bit (struct gdbarch *gdbarch, struct regcache *regs,
- arm_displaced_step_closure *dsc,
+ arm_displaced_step_copy_insn_closure *dsc,
int rd, unsigned int imm)
{
static int
thumb_decode_pc_relative_16bit (struct gdbarch *gdbarch, uint16_t insn,
struct regcache *regs,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
unsigned int rd = bits (insn, 8, 10);
unsigned int imm8 = bits (insn, 0, 7);
static int
thumb_copy_pc_relative_32bit (struct gdbarch *gdbarch, uint16_t insn1,
uint16_t insn2, struct regcache *regs,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
unsigned int rd = bits (insn2, 8, 11);
/* Since immediate has the same encoding in ADR ADD and SUB, so we simply
static int
thumb_copy_16bit_ldr_literal (struct gdbarch *gdbarch, uint16_t insn1,
struct regcache *regs,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
unsigned int rt = bits (insn1, 8, 10);
unsigned int pc;
static int
thumb_copy_cbnz_cbz (struct gdbarch *gdbarch, uint16_t insn1,
struct regcache *regs,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
int non_zero = bit (insn1, 11);
unsigned int imm5 = (bit (insn1, 9) << 6) | (bits (insn1, 3, 7) << 1);
static int
thumb2_copy_table_branch (struct gdbarch *gdbarch, uint16_t insn1,
uint16_t insn2, struct regcache *regs,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
ULONGEST rn_val, rm_val;
int is_tbh = bit (insn2, 4);
static void
cleanup_pop_pc_16bit_all (struct gdbarch *gdbarch, struct regcache *regs,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
/* PC <- r7 */
int val = displaced_read_reg (regs, dsc, 7);
static int
thumb_copy_pop_pc_16bit (struct gdbarch *gdbarch, uint16_t insn1,
struct regcache *regs,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
dsc->u.block.regmask = insn1 & 0x00ff;
static void
thumb_process_displaced_16bit_insn (struct gdbarch *gdbarch, uint16_t insn1,
struct regcache *regs,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
unsigned short op_bit_12_15 = bits (insn1, 12, 15);
unsigned short op_bit_10_11 = bits (insn1, 10, 11);
decode_thumb_32bit_ld_mem_hints (struct gdbarch *gdbarch,
uint16_t insn1, uint16_t insn2,
struct regcache *regs,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
int rt = bits (insn2, 12, 15);
int rn = bits (insn1, 0, 3);
static void
thumb_process_displaced_32bit_insn (struct gdbarch *gdbarch, uint16_t insn1,
uint16_t insn2, struct regcache *regs,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
int err = 0;
unsigned short op = bit (insn2, 15);
static void
thumb_process_displaced_insn (struct gdbarch *gdbarch, CORE_ADDR from,
struct regcache *regs,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
uint16_t insn1
void
arm_process_displaced_insn (struct gdbarch *gdbarch, CORE_ADDR from,
CORE_ADDR to, struct regcache *regs,
- arm_displaced_step_closure *dsc)
+ arm_displaced_step_copy_insn_closure *dsc)
{
int err = 0;
enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
void
arm_displaced_init_closure (struct gdbarch *gdbarch, CORE_ADDR from,
- CORE_ADDR to, arm_displaced_step_closure *dsc)
+ CORE_ADDR to,
+ arm_displaced_step_copy_insn_closure *dsc)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ arm_gdbarch_tdep *tdep = (arm_gdbarch_tdep *) gdbarch_tdep (gdbarch);
unsigned int i, len, offset;
enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
int size = dsc->is_thumb? 2 : 4;
void
arm_displaced_step_fixup (struct gdbarch *gdbarch,
- struct displaced_step_closure *dsc_,
+ struct displaced_step_copy_insn_closure *dsc_,
CORE_ADDR from, CORE_ADDR to,
struct regcache *regs)
{
- arm_displaced_step_closure *dsc = (arm_displaced_step_closure *) dsc_;
+ arm_displaced_step_copy_insn_closure *dsc
+ = (arm_displaced_step_copy_insn_closure *) dsc_;
if (dsc->cleanup)
dsc->cleanup (gdbarch, regs, dsc);
the assert on the mismatch of info->mach and
bfd_get_mach (current_program_space->exec_bfd ()) in
default_print_insn. */
- if (current_program_space->exec_bfd () != NULL)
+ if (current_program_space->exec_bfd () != NULL
+ && (current_program_space->exec_bfd ()->arch_info
+ == gdbarch_bfd_arch_info (gdbarch)))
info->flags |= USER_SPECIFIED_MACHINE_TYPE;
return default_print_insn (memaddr, info);
static int
arm_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ arm_gdbarch_tdep *tdep = (arm_gdbarch_tdep *) gdbarch_tdep (gdbarch);
enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
if (arm_pc_is_thumb (gdbarch, *pcptr))
static const gdb_byte *
arm_sw_breakpoint_from_kind (struct gdbarch *gdbarch, int kind, int *size)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ arm_gdbarch_tdep *tdep = (arm_gdbarch_tdep *) gdbarch_tdep (gdbarch);
switch (kind)
{
{
struct gdbarch *gdbarch = regs->arch ();
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ arm_gdbarch_tdep *tdep = (arm_gdbarch_tdep *) gdbarch_tdep (gdbarch);
if (TYPE_CODE_FLT == type->code ())
{
- switch (gdbarch_tdep (gdbarch)->fp_model)
+ switch (tdep->fp_model)
{
case ARM_FLOAT_FPA:
{
|| type->code () == TYPE_CODE_BOOL
|| type->code () == TYPE_CODE_PTR
|| TYPE_IS_REFERENCE (type)
- || type->code () == TYPE_CODE_ENUM)
+ || type->code () == TYPE_CODE_ENUM
+ || is_fixed_point_type (type))
{
/* If the type is a plain integer, then the access is
straight-forward. Otherwise we have to play around a bit
return (TYPE_LENGTH (type) > 16);
}
- if (gdbarch_tdep (gdbarch)->arm_abi != ARM_ABI_APCS)
+ arm_gdbarch_tdep *tdep = (arm_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+ if (tdep->arm_abi != ARM_ABI_APCS)
{
/* The AAPCS says all aggregates not larger than a word are returned
in a register. */
- if (TYPE_LENGTH (type) <= ARM_INT_REGISTER_SIZE)
+ if (TYPE_LENGTH (type) <= ARM_INT_REGISTER_SIZE
+ && language_pass_by_reference (type).trivially_copyable)
return 0;
return 1;
/* All aggregate types that won't fit in a register must be returned
in memory. */
- if (TYPE_LENGTH (type) > ARM_INT_REGISTER_SIZE)
+ if (TYPE_LENGTH (type) > ARM_INT_REGISTER_SIZE
+ || !language_pass_by_reference (type).trivially_copyable)
return 1;
/* In the ARM ABI, "integer" like aggregate types are returned in
}
/* If bitpos != 0, then we have to care about it. */
- if (TYPE_FIELD_BITPOS (type, i) != 0)
+ if (type->field (i).loc_bitpos () != 0)
{
/* Bitfields are not addressable. If the field bitsize is
zero, then the field is not packed. Hence it cannot be
if (type->code () == TYPE_CODE_FLT)
{
gdb_byte buf[ARM_FP_REGISTER_SIZE];
+ arm_gdbarch_tdep *tdep = (arm_gdbarch_tdep *) gdbarch_tdep (gdbarch);
- switch (gdbarch_tdep (gdbarch)->fp_model)
+ switch (tdep->fp_model)
{
case ARM_FLOAT_FPA:
struct type *valtype, struct regcache *regcache,
gdb_byte *readbuf, const gdb_byte *writebuf)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ arm_gdbarch_tdep *tdep = (arm_gdbarch_tdep *) gdbarch_tdep (gdbarch);
struct type *func_type = function ? value_type (function) : NULL;
enum arm_vfp_cprc_base_type vfp_base_type;
int vfp_base_count;
|| valtype->code () == TYPE_CODE_UNION
|| valtype->code () == TYPE_CODE_ARRAY)
{
+ /* From the AAPCS document:
+
+ Result return:
+
+ A Composite Type larger than 4 bytes, or whose size cannot be
+ determined statically by both caller and callee, is stored in memory
+ at an address passed as an extra argument when the function was
+ called (Parameter Passing, rule A.4). The memory to be used for the
+ result may be modified at any point during the function call.
+
+ Parameter Passing:
+
+ A.4: If the subroutine is a function that returns a result in memory,
+ then the address for the result is placed in r0 and the NCRN is set
+ to r1. */
if (tdep->struct_return == pcc_struct_return
|| arm_return_in_memory (gdbarch, valtype))
- return RETURN_VALUE_STRUCT_CONVENTION;
+ {
+ if (readbuf)
+ {
+ CORE_ADDR addr;
+
+ regcache->cooked_read (ARM_A1_REGNUM, &addr);
+ read_memory (addr, readbuf, TYPE_LENGTH (valtype));
+ }
+ return RETURN_VALUE_ABI_RETURNS_ADDRESS;
+ }
}
else if (valtype->code () == TYPE_CODE_COMPLEX)
{
arm_get_longjmp_target (struct frame_info *frame, CORE_ADDR *pc)
{
struct gdbarch *gdbarch = get_frame_arch (frame);
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ arm_gdbarch_tdep *tdep = (arm_gdbarch_tdep *) gdbarch_tdep (gdbarch);
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
CORE_ADDR jb_addr;
gdb_byte buf[ARM_INT_REGISTER_SIZE];
static void
arm_update_current_architecture (void)
{
- struct gdbarch_info info;
-
/* If the current architecture is not ARM, we have nothing to do. */
if (gdbarch_bfd_arch_info (target_gdbarch ())->arch != bfd_arch_arm)
return;
/* Update the architecture. */
- gdbarch_info_init (&info);
-
+ gdbarch_info info;
if (!gdbarch_update_p (info))
internal_error (__FILE__, __LINE__, _("could not update architecture"));
}
show_fp_model (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (target_gdbarch ());
+ arm_gdbarch_tdep *tdep
+ = (arm_gdbarch_tdep *) gdbarch_tdep (target_gdbarch ());
if (arm_fp_model == ARM_FLOAT_AUTO
&& gdbarch_bfd_arch_info (target_gdbarch ())->arch == bfd_arch_arm)
- fprintf_filtered (file, _("\
+ gdb_printf (file, _("\
The current ARM floating point model is \"auto\" (currently \"%s\").\n"),
- fp_model_strings[tdep->fp_model]);
+ fp_model_strings[tdep->fp_model]);
else
- fprintf_filtered (file, _("\
+ gdb_printf (file, _("\
The current ARM floating point model is \"%s\".\n"),
- fp_model_strings[arm_fp_model]);
+ fp_model_strings[arm_fp_model]);
}
static void
arm_show_abi (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (target_gdbarch ());
+ arm_gdbarch_tdep *tdep
+ = (arm_gdbarch_tdep *) gdbarch_tdep (target_gdbarch ());
if (arm_abi_global == ARM_ABI_AUTO
&& gdbarch_bfd_arch_info (target_gdbarch ())->arch == bfd_arch_arm)
- fprintf_filtered (file, _("\
+ gdb_printf (file, _("\
The current ARM ABI is \"auto\" (currently \"%s\").\n"),
- arm_abi_strings[tdep->arm_abi]);
+ arm_abi_strings[tdep->arm_abi]);
else
- fprintf_filtered (file, _("The current ARM ABI is \"%s\".\n"),
- arm_abi_string);
+ gdb_printf (file, _("The current ARM ABI is \"%s\".\n"),
+ arm_abi_string);
}
static void
arm_show_fallback_mode (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
- fprintf_filtered (file,
- _("The current execution mode assumed "
- "(when symbols are unavailable) is \"%s\".\n"),
- arm_fallback_mode_string);
+ gdb_printf (file,
+ _("The current execution mode assumed "
+ "(when symbols are unavailable) is \"%s\".\n"),
+ arm_fallback_mode_string);
}
static void
arm_show_force_mode (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
- fprintf_filtered (file,
- _("The current execution mode assumed "
- "(even when symbols are available) is \"%s\".\n"),
- arm_force_mode_string);
+ gdb_printf (file,
+ _("The current execution mode assumed "
+ "(even when symbols are available) is \"%s\".\n"),
+ arm_force_mode_string);
}
/* If the user changes the register disassembly style used for info
const char *opt;
FOR_EACH_DISASSEMBLER_OPTION (opt, options)
- if (CONST_STRNEQ (opt, "reg-names-"))
+ if (startswith (opt, "reg-names-"))
{
style = &opt[strlen ("reg-names-")];
len = strcspn (style, ",");
}
- fprintf_unfiltered (file, "The disassembly style is \"%.*s\".\n", len, style);
+ gdb_printf (file, "The disassembly style is \"%.*s\".\n", len, style);
}
\f
/* Return the ARM register name corresponding to register I. */
static const char *
arm_register_name (struct gdbarch *gdbarch, int i)
{
- const int num_regs = gdbarch_num_regs (gdbarch);
+ arm_gdbarch_tdep *tdep = (arm_gdbarch_tdep *) gdbarch_tdep (gdbarch);
- if (gdbarch_tdep (gdbarch)->have_vfp_pseudos
- && i >= num_regs && i < num_regs + 32)
+ if (is_s_pseudo (gdbarch, i))
{
- static const char *const vfp_pseudo_names[] = {
+ static const char *const s_pseudo_names[] = {
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
"s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15",
"s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23",
"s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
};
- return vfp_pseudo_names[i - num_regs];
+ return s_pseudo_names[i - tdep->s_pseudo_base];
}
- if (gdbarch_tdep (gdbarch)->have_neon_pseudos
- && i >= num_regs + 32 && i < num_regs + 32 + 16)
+ if (is_q_pseudo (gdbarch, i))
{
- static const char *const neon_pseudo_names[] = {
+ static const char *const q_pseudo_names[] = {
"q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7",
"q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15",
};
- return neon_pseudo_names[i - num_regs - 32];
+ return q_pseudo_names[i - tdep->q_pseudo_base];
}
+ if (is_mve_pseudo (gdbarch, i))
+ return "p0";
+
if (i >= ARRAY_SIZE (arm_register_names))
/* These registers are only supported on targets which supply
an XML description. */
return "";
+ /* Non-pseudo registers. */
return arm_register_names[i];
}
return REG_VALID;
}
+/* Read the contents of the MVE pseudo register REGNUM and store it
+ in BUF. */
+
+static enum register_status
+arm_mve_pseudo_read (struct gdbarch *gdbarch, readable_regcache *regcache,
+ int regnum, gdb_byte *buf)
+{
+ arm_gdbarch_tdep *tdep = (arm_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+
+ /* P0 is the first 16 bits of VPR. */
+ return regcache->raw_read_part (tdep->mve_vpr_regnum, 0, 2, buf);
+}
+
static enum register_status
arm_pseudo_read (struct gdbarch *gdbarch, readable_regcache *regcache,
int regnum, gdb_byte *buf)
char name_buf[4];
gdb_byte reg_buf[8];
int offset, double_regnum;
+ arm_gdbarch_tdep *tdep = (arm_gdbarch_tdep *) gdbarch_tdep (gdbarch);
gdb_assert (regnum >= num_regs);
- regnum -= num_regs;
- if (gdbarch_tdep (gdbarch)->have_neon_pseudos && regnum >= 32 && regnum < 48)
- /* Quad-precision register. */
- return arm_neon_quad_read (gdbarch, regcache, regnum - 32, buf);
+ if (is_q_pseudo (gdbarch, regnum))
+ {
+ /* Quad-precision register. */
+ return arm_neon_quad_read (gdbarch, regcache,
+ regnum - tdep->q_pseudo_base, buf);
+ }
+ else if (is_mve_pseudo (gdbarch, regnum))
+ return arm_mve_pseudo_read (gdbarch, regcache, regnum, buf);
else
{
enum register_status status;
+ regnum -= tdep->s_pseudo_base;
/* Single-precision register. */
gdb_assert (regnum < 32);
regcache->raw_write (double_regnum + 1, buf + offset);
}
+/* Store the contents of BUF to the MVE pseudo register REGNUM. */
+
+static void
+arm_mve_pseudo_write (struct gdbarch *gdbarch, struct regcache *regcache,
+ int regnum, const gdb_byte *buf)
+{
+ arm_gdbarch_tdep *tdep = (arm_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+
+ /* P0 is the first 16 bits of VPR. */
+ regcache->raw_write_part (tdep->mve_vpr_regnum, 0, 2, buf);
+}
+
static void
arm_pseudo_write (struct gdbarch *gdbarch, struct regcache *regcache,
int regnum, const gdb_byte *buf)
char name_buf[4];
gdb_byte reg_buf[8];
int offset, double_regnum;
+ arm_gdbarch_tdep *tdep = (arm_gdbarch_tdep *) gdbarch_tdep (gdbarch);
gdb_assert (regnum >= num_regs);
- regnum -= num_regs;
- if (gdbarch_tdep (gdbarch)->have_neon_pseudos && regnum >= 32 && regnum < 48)
- /* Quad-precision register. */
- arm_neon_quad_write (gdbarch, regcache, regnum - 32, buf);
+ if (is_q_pseudo (gdbarch, regnum))
+ {
+ /* Quad-precision register. */
+ arm_neon_quad_write (gdbarch, regcache,
+ regnum - tdep->q_pseudo_base, buf);
+ }
+ else if (is_mve_pseudo (gdbarch, regnum))
+ arm_mve_pseudo_write (gdbarch, regcache, regnum, buf);
else
{
+ regnum -= tdep->s_pseudo_base;
/* Single-precision register. */
gdb_assert (regnum < 32);
static void
arm_register_g_packet_guesses (struct gdbarch *gdbarch)
{
- if (gdbarch_tdep (gdbarch)->is_m)
+ arm_gdbarch_tdep *tdep = (arm_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+
+ if (tdep->is_m)
{
const target_desc *tdesc;
register_remote_g_packet_guess (gdbarch,
ARM_CORE_REGS_SIZE + ARM_VFP2_REGS_SIZE,
tdesc);
+ /* M-profile plus MVE. */
+ tdesc = arm_read_mprofile_description (ARM_M_TYPE_MVE);
+ register_remote_g_packet_guess (gdbarch, ARM_CORE_REGS_SIZE
+ + ARM_VFP2_REGS_SIZE
+ + ARM_INT_REGISTER_SIZE, tdesc);
}
/* Otherwise we don't have a useful guess. */
static int
arm_code_of_frame_writable (struct gdbarch *gdbarch, struct frame_info *frame)
{
- if (gdbarch_tdep (gdbarch)->is_m
- && get_frame_type (frame) == SIGTRAMP_FRAME)
+ arm_gdbarch_tdep *tdep = (arm_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+
+ if (tdep->is_m && get_frame_type (frame) == SIGTRAMP_FRAME)
{
/* M-profile exception frames return to some magic PCs, where
isn't writable at all. */
static struct gdbarch *
arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
{
- struct gdbarch_tdep *tdep;
struct gdbarch *gdbarch;
struct gdbarch_list *best_arch;
enum arm_abi_kind arm_abi = arm_abi_global;
int i;
bool is_m = false;
int vfp_register_count = 0;
- bool have_vfp_pseudos = false, have_neon_pseudos = false;
+ bool have_s_pseudos = false, have_q_pseudos = false;
bool have_wmmx_registers = false;
bool have_neon = false;
bool have_fpa_registers = true;
const struct target_desc *tdesc = info.target_desc;
+ bool have_vfp = false;
+ bool have_mve = false;
+ int mve_vpr_regnum = -1;
+ int register_count = ARM_NUM_REGS;
/* If we have an object to base this architecture on, try to determine
its ABI. */
if (!tdesc_has_registers (tdesc)
&& (attr_arch == TAG_CPU_ARCH_V6_M
|| attr_arch == TAG_CPU_ARCH_V6S_M
+ || attr_arch == TAG_CPU_ARCH_V7E_M
+ || attr_arch == TAG_CPU_ARCH_V8M_BASE
+ || attr_arch == TAG_CPU_ARCH_V8M_MAIN
+ || attr_arch == TAG_CPU_ARCH_V8_1M_MAIN
|| attr_profile == 'M'))
is_m = true;
#endif
if (!valid_p)
return NULL;
+ have_vfp = true;
+
if (tdesc_unnumbered_register (feature, "s0") == 0)
- have_vfp_pseudos = true;
+ have_s_pseudos = true;
vfp_register_count = i;
their type; otherwise (normally) provide them with
the default type. */
if (tdesc_unnumbered_register (feature, "q0") == 0)
- have_neon_pseudos = true;
+ have_q_pseudos = true;
+ }
+ }
+
+ /* Check for MVE after all the checks for GPR's, VFP and Neon.
+ MVE (Helium) is an M-profile extension. */
+ if (is_m)
+ {
+ /* Do we have the MVE feature? */
+ feature = tdesc_find_feature (tdesc,"org.gnu.gdb.arm.m-profile-mve");
+
+ if (feature != nullptr)
+ {
+ /* If we have MVE, we must always have the VPR register. */
+ valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
+ register_count, "vpr");
+ if (!valid_p)
+ {
+ warning (_("MVE feature is missing required register vpr."));
+ return nullptr;
+ }
+
+ have_mve = true;
+ mve_vpr_regnum = register_count;
+ register_count++;
+
+ /* We can't have Q pseudo registers available here, as that
+ would mean we have NEON features, and that is only available
+ on A and R profiles. */
+ gdb_assert (!have_q_pseudos);
- have_neon = true;
+ /* Given we have a M-profile target description, if MVE is
+ enabled and there are VFP registers, we should have Q
+ pseudo registers (Q0 ~ Q7). */
+ if (have_vfp)
+ have_q_pseudos = true;
}
}
}
best_arch != NULL;
best_arch = gdbarch_list_lookup_by_info (best_arch->next, &info))
{
- if (arm_abi != ARM_ABI_AUTO
- && arm_abi != gdbarch_tdep (best_arch->gdbarch)->arm_abi)
+ arm_gdbarch_tdep *tdep
+ = (arm_gdbarch_tdep *) gdbarch_tdep (best_arch->gdbarch);
+
+ if (arm_abi != ARM_ABI_AUTO && arm_abi != tdep->arm_abi)
continue;
- if (fp_model != ARM_FLOAT_AUTO
- && fp_model != gdbarch_tdep (best_arch->gdbarch)->fp_model)
+ if (fp_model != ARM_FLOAT_AUTO && fp_model != tdep->fp_model)
continue;
/* There are various other properties in tdep that we do not
automatically disqualified. */
/* Do check is_m, though, since it might come from the binary. */
- if (is_m != gdbarch_tdep (best_arch->gdbarch)->is_m)
+ if (is_m != tdep->is_m)
continue;
/* Found a match. */
if (best_arch != NULL)
return best_arch->gdbarch;
- tdep = XCNEW (struct gdbarch_tdep);
+ arm_gdbarch_tdep *tdep = new arm_gdbarch_tdep;
gdbarch = gdbarch_alloc (&info, tdep);
/* Record additional information about the architecture we are defining.
|| vfp_register_count == 16
|| vfp_register_count == 32);
tdep->vfp_register_count = vfp_register_count;
- tdep->have_vfp_pseudos = have_vfp_pseudos;
- tdep->have_neon_pseudos = have_neon_pseudos;
+ tdep->have_s_pseudos = have_s_pseudos;
+ tdep->have_q_pseudos = have_q_pseudos;
tdep->have_neon = have_neon;
+ /* Adjust the MVE feature settings. */
+ if (have_mve)
+ {
+ tdep->have_mve = true;
+ tdep->mve_vpr_regnum = mve_vpr_regnum;
+ }
+
arm_register_g_packet_guesses (gdbarch);
/* Breakpoints. */
/* Information about registers, etc. */
set_gdbarch_sp_regnum (gdbarch, ARM_SP_REGNUM);
set_gdbarch_pc_regnum (gdbarch, ARM_PC_REGNUM);
- set_gdbarch_num_regs (gdbarch, ARM_NUM_REGS);
+ set_gdbarch_num_regs (gdbarch, register_count);
set_gdbarch_register_type (gdbarch, arm_register_type);
set_gdbarch_register_reggroup_p (gdbarch, arm_register_reggroup_p);
/* This "info float" is FPA-specific. Use the generic version if we
do not have FPA. */
- if (gdbarch_tdep (gdbarch)->have_fpa_registers)
+ if (tdep->have_fpa_registers)
set_gdbarch_print_float_info (gdbarch, arm_print_float_info);
/* Internal <-> external register number maps. */
set_gdbarch_long_double_format (gdbarch, floatformats_ieee_double);
}
- if (have_vfp_pseudos)
- {
- /* NOTE: These are the only pseudo registers used by
- the ARM target at the moment. If more are added, a
- little more care in numbering will be needed. */
-
- int num_pseudos = 32;
- if (have_neon_pseudos)
- num_pseudos += 16;
- set_gdbarch_num_pseudo_regs (gdbarch, num_pseudos);
- set_gdbarch_pseudo_register_read (gdbarch, arm_pseudo_read);
- set_gdbarch_pseudo_register_write (gdbarch, arm_pseudo_write);
- }
-
if (tdesc_data != nullptr)
{
set_tdesc_pseudo_register_name (gdbarch, arm_register_name);
tdesc_use_registers (gdbarch, tdesc, std::move (tdesc_data));
+ register_count = gdbarch_num_regs (gdbarch);
/* Override tdesc_register_type to adjust the types of VFP
registers for NEON. */
set_gdbarch_register_type (gdbarch, arm_register_type);
}
+ /* Initialize the pseudo register data. */
+ int num_pseudos = 0;
+ if (tdep->have_s_pseudos)
+ {
+ /* VFP single precision pseudo registers (S0~S31). */
+ tdep->s_pseudo_base = register_count;
+ tdep->s_pseudo_count = 32;
+ num_pseudos += tdep->s_pseudo_count;
+
+ if (tdep->have_q_pseudos)
+ {
+ /* NEON quad precision pseudo registers (Q0~Q15). */
+ tdep->q_pseudo_base = register_count + num_pseudos;
+
+ if (have_neon)
+ tdep->q_pseudo_count = 16;
+ else if (have_mve)
+ tdep->q_pseudo_count = ARM_MVE_NUM_Q_REGS;
+
+ num_pseudos += tdep->q_pseudo_count;
+ }
+ }
+
+ /* Do we have any MVE pseudo registers? */
+ if (have_mve)
+ {
+ tdep->mve_pseudo_base = register_count + num_pseudos;
+ tdep->mve_pseudo_count = 1;
+ num_pseudos += tdep->mve_pseudo_count;
+ }
+
+ /* Set some pseudo register hooks, if we have pseudo registers. */
+ if (tdep->have_s_pseudos || have_mve)
+ {
+ set_gdbarch_num_pseudo_regs (gdbarch, num_pseudos);
+ set_gdbarch_pseudo_register_read (gdbarch, arm_pseudo_read);
+ set_gdbarch_pseudo_register_write (gdbarch, arm_pseudo_write);
+ }
+
/* Add standard register aliases. We add aliases even for those
names which are used by the current architecture - it's simpler,
and does no harm, since nothing ever lists user registers. */
static void
arm_dump_tdep (struct gdbarch *gdbarch, struct ui_file *file)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ arm_gdbarch_tdep *tdep = (arm_gdbarch_tdep *) gdbarch_tdep (gdbarch);
if (tdep == NULL)
return;
- fprintf_unfiltered (file, _("arm_dump_tdep: fp_model = %i\n"),
- (int) tdep->fp_model);
- fprintf_unfiltered (file, _("arm_dump_tdep: have_fpa_registers = %i\n"),
- (int) tdep->have_fpa_registers);
- fprintf_unfiltered (file, _("arm_dump_tdep: have_wmmx_registers = %i\n"),
- (int) tdep->have_wmmx_registers);
- fprintf_unfiltered (file, _("arm_dump_tdep: vfp_register_count = %i\n"),
- (int) tdep->vfp_register_count);
- fprintf_unfiltered (file, _("arm_dump_tdep: have_vfp_pseudos = %i\n"),
- (int) tdep->have_vfp_pseudos);
- fprintf_unfiltered (file, _("arm_dump_tdep: have_neon_pseudos = %i\n"),
- (int) tdep->have_neon_pseudos);
- fprintf_unfiltered (file, _("arm_dump_tdep: have_neon = %i\n"),
- (int) tdep->have_neon);
- fprintf_unfiltered (file, _("arm_dump_tdep: Lowest pc = 0x%lx\n"),
- (unsigned long) tdep->lowest_pc);
+ gdb_printf (file, _("arm_dump_tdep: fp_model = %i\n"),
+ (int) tdep->fp_model);
+ gdb_printf (file, _("arm_dump_tdep: have_fpa_registers = %i\n"),
+ (int) tdep->have_fpa_registers);
+ gdb_printf (file, _("arm_dump_tdep: have_wmmx_registers = %i\n"),
+ (int) tdep->have_wmmx_registers);
+ gdb_printf (file, _("arm_dump_tdep: vfp_register_count = %i\n"),
+ (int) tdep->vfp_register_count);
+ gdb_printf (file, _("arm_dump_tdep: have_s_pseudos = %s\n"),
+ tdep->have_s_pseudos? "true" : "false");
+ gdb_printf (file, _("arm_dump_tdep: s_pseudo_base = %i\n"),
+ (int) tdep->s_pseudo_base);
+ gdb_printf (file, _("arm_dump_tdep: s_pseudo_count = %i\n"),
+ (int) tdep->s_pseudo_count);
+ gdb_printf (file, _("arm_dump_tdep: have_q_pseudos = %s\n"),
+ tdep->have_q_pseudos? "true" : "false");
+ gdb_printf (file, _("arm_dump_tdep: q_pseudo_base = %i\n"),
+ (int) tdep->q_pseudo_base);
+ gdb_printf (file, _("arm_dump_tdep: q_pseudo_count = %i\n"),
+ (int) tdep->q_pseudo_count);
+ gdb_printf (file, _("arm_dump_tdep: have_neon = %i\n"),
+ (int) tdep->have_neon);
+ gdb_printf (file, _("arm_dump_tdep: have_mve = %s\n"),
+ tdep->have_mve? "yes" : "no");
+ gdb_printf (file, _("arm_dump_tdep: mve_vpr_regnum = %i\n"),
+ tdep->mve_vpr_regnum);
+ gdb_printf (file, _("arm_dump_tdep: mve_pseudo_base = %i\n"),
+ tdep->mve_pseudo_base);
+ gdb_printf (file, _("arm_dump_tdep: mve_pseudo_count = %i\n"),
+ tdep->mve_pseudo_count);
+ gdb_printf (file, _("arm_dump_tdep: Lowest pc = 0x%lx\n"),
+ (unsigned long) tdep->lowest_pc);
}
#if GDB_SELF_TEST
gdbarch_register (bfd_arch_arm, arm_gdbarch_init, arm_dump_tdep);
/* Add ourselves to objfile event chain. */
- gdb::observers::new_objfile.attach (arm_exidx_new_objfile);
+ gdb::observers::new_objfile.attach (arm_exidx_new_objfile, "arm-tdep");
/* Register an ELF OS ABI sniffer for ARM binaries. */
gdbarch_register_osabi_sniffer (bfd_arch_arm,
arm_elf_osabi_sniffer);
/* Add root prefix command for all "set arm"/"show arm" commands. */
- add_basic_prefix_cmd ("arm", no_class,
- _("Various ARM-specific commands."),
- &setarmcmdlist, "set arm ", 0, &setlist);
-
- add_show_prefix_cmd ("arm", no_class,
- _("Various ARM-specific commands."),
- &showarmcmdlist, "show arm ", 0, &showlist);
-
+ add_setshow_prefix_cmd ("arm", no_class,
+ _("Various ARM-specific commands."),
+ _("Various ARM-specific commands."),
+ &setarmcmdlist, &showarmcmdlist,
+ &setlist, &showlist);
arm_disassembler_options = xstrdup ("reg-names-std");
const disasm_options_t *disasm_options
= &disassembler_options_arm ()->options;
int num_disassembly_styles = 0;
for (i = 0; disasm_options->name[i] != NULL; i++)
- if (CONST_STRNEQ (disasm_options->name[i], "reg-names-"))
+ if (startswith (disasm_options->name[i], "reg-names-"))
num_disassembly_styles++;
/* Initialize the array that will be passed to add_setshow_enum_cmd(). */
valid_disassembly_styles = XNEWVEC (const char *,
num_disassembly_styles + 1);
for (i = j = 0; disasm_options->name[i] != NULL; i++)
- if (CONST_STRNEQ (disasm_options->name[i], "reg-names-"))
+ if (startswith (disasm_options->name[i], "reg-names-"))
{
size_t offset = strlen ("reg-names-");
const char *style = disasm_options->name[i];
valid_disassembly_styles[j++] = &style[offset];
+ if (strcmp (&style[offset], "std") == 0)
+ disassembly_style = &style[offset];
length = snprintf (rdptr, rest, "%s - %s\n", &style[offset],
disasm_options->description[i]);
rdptr += length;
{ \
unsigned int mem_len = LENGTH; \
if (mem_len) \
- { \
- MEMS = XNEWVEC (struct arm_mem_r, mem_len); \
- memcpy(&MEMS->len, &RECORD_BUF[0], \
- sizeof(struct arm_mem_r) * LENGTH); \
- } \
+ { \
+ MEMS = XNEWVEC (struct arm_mem_r, mem_len); \
+ memcpy(&MEMS->len, &RECORD_BUF[0], \
+ sizeof(struct arm_mem_r) * LENGTH); \
+ } \
} \
while (0)
{
/* Handle MLA(S) and MUL(S). */
if (in_inclusive_range (insn_op1, 0U, 3U))
- {
- record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
- record_buf[1] = ARM_PS_REGNUM;
- arm_insn_r->reg_rec_count = 2;
- }
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
else if (in_inclusive_range (insn_op1, 4U, 15U))
- {
- /* Handle SMLAL(S), SMULL(S), UMLAL(S), UMULL(S). */
- record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
- record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
- record_buf[2] = ARM_PS_REGNUM;
- arm_insn_r->reg_rec_count = 3;
- }
+ {
+ /* Handle SMLAL(S), SMULL(S), UMLAL(S), UMULL(S). */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[2] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 3;
+ }
}
opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
/* Handle multiply instructions. */
/* MLA, MUL, SMLAL, SMULL, UMLAL, UMULL. */
if (0 == arm_insn_r->opcode || 1 == arm_insn_r->opcode)
- {
- /* Handle MLA and MUL. */
- record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
- record_buf[1] = ARM_PS_REGNUM;
- arm_insn_r->reg_rec_count = 2;
- }
- else if (4 <= arm_insn_r->opcode && 7 >= arm_insn_r->opcode)
- {
- /* Handle SMLAL, SMULL, UMLAL, UMULL. */
- record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
- record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
- record_buf[2] = ARM_PS_REGNUM;
- arm_insn_r->reg_rec_count = 3;
- }
+ {
+ /* Handle MLA and MUL. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (4 <= arm_insn_r->opcode && 7 >= arm_insn_r->opcode)
+ {
+ /* Handle SMLAL, SMULL, UMLAL, UMULL. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[2] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 3;
+ }
}
else if (9 == arm_insn_r->decode && opcode1 > 0x10)
{
/* Note: BLX(1) doesnt fall here but instead it falls into
extension space. */
if (bit (arm_insn_r->arm_insn, 24))
- {
- record_buf[0] = ARM_LR_REGNUM;
- arm_insn_r->reg_rec_count = 1;
- }
+ {
+ record_buf[0] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf);
static int
arm_record_unsupported_insn (insn_decode_record *arm_insn_r)
{
- printf_unfiltered (_("Process record does not support instruction "
- "0x%0x at address %s.\n"),arm_insn_r->arm_insn,
- paddress (arm_insn_r->gdbarch, arm_insn_r->this_addr));
+ gdb_printf (gdb_stderr,
+ _("Process record does not support instruction "
+ "0x%0x at address %s.\n"),arm_insn_r->arm_insn,
+ paddress (arm_insn_r->gdbarch, arm_insn_r->this_addr));
return -1;
}
arm_record_coproc_data_proc (insn_decode_record *arm_insn_r)
{
uint32_t op, op1_ebit, coproc, bits_24_25;
- struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+ arm_gdbarch_tdep *tdep
+ = (arm_gdbarch_tdep *) gdbarch_tdep (arm_insn_r->gdbarch);
struct regcache *reg_cache = arm_insn_r->regcache;
arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 24, 27);
}
else
{
- printf_unfiltered (_("no syscall record support\n"));
+ gdb_printf (gdb_stderr, _("no syscall record support\n"));
return -1;
}
}
record_buf[1] = ARM_LR_REGNUM;
thumb_insn_r->reg_rec_count = 2;
/* We need to save SPSR value, which is not yet done. */
- printf_unfiltered (_("Process record does not support instruction "
- "0x%0x at address %s.\n"),
- thumb_insn_r->arm_insn,
- paddress (thumb_insn_r->gdbarch,
- thumb_insn_r->this_addr));
+ gdb_printf (gdb_stderr,
+ _("Process record does not support instruction "
+ "0x%0x at address %s.\n"),
+ thumb_insn_r->arm_insn,
+ paddress (thumb_insn_r->gdbarch,
+ thumb_insn_r->this_addr));
return -1;
case 0xf:
/* Handling opcode 110 insns. */
static int
-thumb_record_ldm_stm_swi (insn_decode_record *thumb_insn_r)
+thumb_record_ldm_stm_swi (insn_decode_record *thumb_insn_r)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+ arm_gdbarch_tdep *tdep
+ = (arm_gdbarch_tdep *) gdbarch_tdep (thumb_insn_r->gdbarch);
struct regcache *reg_cache = thumb_insn_r->regcache;
uint32_t ret = 0; /* function return value: -1:record failure ; 0:success */
}
else
{
- printf_unfiltered (_("no syscall record support\n"));
+ gdb_printf (gdb_stderr, _("no syscall record support\n"));
return -1;
}
}
{
if (record_debug)
{
- printf_unfiltered (_("Process record: error reading memory at "
- "addr %s len = %d.\n"),
- paddress (arm_record->gdbarch,
- arm_record->this_addr), insn_size);
+ gdb_printf (gdb_stdlog,
+ _("Process record: error reading memory at "
+ "addr %s len = %d.\n"),
+ paddress (arm_record->gdbarch,
+ arm_record->this_addr), insn_size);
}
return -1;
}
arm_record_test (void)
{
struct gdbarch_info info;
- gdbarch_info_init (&info);
info.bfd_arch_info = bfd_scan_arch ("arm");
struct gdbarch *gdbarch = gdbarch_find_by_info (info);
for (bfd_endian endianness : {BFD_ENDIAN_LITTLE, BFD_ENDIAN_BIG})
{
struct gdbarch_info info;
- gdbarch_info_init (&info);
info.byte_order = endianness;
info.byte_order_for_code = endianness;
info.bfd_arch_info = bfd_scan_arch ("arm");
if (record_debug > 1)
{
- fprintf_unfiltered (gdb_stdlog, "Process record: arm_process_record "
- "addr = %s\n",
- paddress (gdbarch, arm_record.this_addr));
+ gdb_printf (gdb_stdlog, "Process record: arm_process_record "
+ "addr = %s\n",
+ paddress (gdbarch, arm_record.this_addr));
}
instruction_reader reader;
{
if (record_debug)
{
- printf_unfiltered (_("Process record: error reading memory at "
- "addr %s len = %d.\n"),
- paddress (arm_record.gdbarch,
- arm_record.this_addr), 2);
+ gdb_printf (gdb_stdlog,
+ _("Process record: error reading memory at "
+ "addr %s len = %d.\n"),
+ paddress (arm_record.gdbarch,
+ arm_record.this_addr), 2);
}
return -1;
}