/* Common target dependent code for GDB on ARM systems.
- Copyright (C) 1988-2019 Free Software Foundation, Inc.
+ Copyright (C) 1988-2020 Free Software Foundation, Inc.
This file is part of GDB.
#include "frame-base.h"
#include "trad-frame.h"
#include "objfiles.h"
-#include "dwarf2-frame.h"
+#include "dwarf2/frame.h"
#include "gdbtypes.h"
#include "prologue-value.h"
#include "remote.h"
#include "target-descriptions.h"
#include "user-regs.h"
#include "observable.h"
+#include "count-one-bits.h"
#include "arch/arm.h"
#include "arch/arm-get-next-pcs.h"
#include "record-full.h"
#include <algorithm>
+#include "producer.h"
+
#if GDB_SELF_TEST
#include "gdbsupport/selftest.h"
#endif
struct arm_mapping_symbol
{
- bfd_vma value;
+ CORE_ADDR value;
char type;
bool operator< (const arm_mapping_symbol &other) const
typedef std::vector<arm_mapping_symbol> arm_mapping_symbol_vec;
-struct arm_per_objfile
+struct arm_per_bfd
{
- explicit arm_per_objfile (size_t num_sections)
+ explicit arm_per_bfd (size_t num_sections)
: section_maps (new arm_mapping_symbol_vec[num_sections]),
section_maps_sorted (new bool[num_sections] ())
{}
- DISABLE_COPY_AND_ASSIGN (arm_per_objfile);
+ DISABLE_COPY_AND_ASSIGN (arm_per_bfd);
/* Information about mapping symbols ($a, $d, $t) in the objfile.
std::unique_ptr<bool[]> section_maps_sorted;
};
-/* Per-objfile data used for mapping symbols. */
-static objfile_key<arm_per_objfile> arm_objfile_data_key;
+/* Per-bfd data used for mapping symbols. */
+static bfd_key<arm_per_bfd> arm_bfd_data_key;
/* The list of available "set arm ..." and "show arm ..." commands. */
static struct cmd_list_element *setarmcmdlist = NULL;
sec = find_pc_section (memaddr);
if (sec != NULL)
{
- arm_per_objfile *data = arm_objfile_data_key.get (sec->objfile);
+ arm_per_bfd *data = arm_bfd_data_key.get (sec->objfile->obfd);
if (data != NULL)
{
unsigned int section_idx = sec->the_bfd_section->index;
"display/i $pc" always show the correct mode (though if there is
a symbol table we will not reach here, so it still may not be
displayed in the mode it will be executed). */
- if (target_has_registers)
+ if (target_has_registers ())
return arm_frame_is_thumb (get_current_frame ());
/* Otherwise we're out of luck; we assume ARM. */
}
/* Determine if the address specified equals any of these magic return
- values, called EXC_RETURN, defined by the ARM v6-M and v7-M
+ values, called EXC_RETURN, defined by the ARM v6-M, v7-M and v8-M
architectures.
From ARMv6-M Reference Manual B1.5.8
0xFFFFFFFD Thread mode Process Basic
For more details see "B1.5.8 Exception return behavior"
- in both ARMv6-M and ARMv7-M Architecture Reference Manuals. */
+ in both ARMv6-M and ARMv7-M Architecture Reference Manuals.
+
+ In the ARMv8-M Architecture Technical Reference also adds
+ for implementations without the Security Extension:
+
+ EXC_RETURN Condition
+ 0xFFFFFFB0 Return to Handler mode.
+ 0xFFFFFFB8 Return to Thread mode using the main stack.
+ 0xFFFFFFBC Return to Thread mode using the process stack. */
static int
arm_m_addr_is_magic (CORE_ADDR addr)
{
switch (addr)
{
+ /* Values from ARMv8-M Architecture Technical Reference. */
+ case 0xffffffb0:
+ case 0xffffffb8:
+ case 0xffffffbc:
/* Values from Tables in B1.5.8 the EXC_RETURN definitions of
the exception return behavior. */
case 0xffffffe1:
msym = lookup_minimal_symbol_by_pc (pc);
if (msym.minsym != NULL
&& BMSYMBOL_VALUE_ADDRESS (msym) == pc
- && MSYMBOL_LINKAGE_NAME (msym.minsym) != NULL)
+ && msym.minsym->linkage_name () != NULL)
{
- const char *name = MSYMBOL_LINKAGE_NAME (msym.minsym);
+ const char *name = msym.minsym->linkage_name ();
/* The GNU linker's Thumb call stub to foo is named
__foo_from_thumb. */
parameters from memory. */
;
- else if ((insn & 0xffb0) == 0xe950 /* ldrd Rt, Rt2,
+ else if ((insn & 0xff70) == 0xe950 /* ldrd Rt, Rt2,
[Rn, #+/-imm] */
&& pv_is_register (regs[bits (insn, 0, 3)], ARM_SP_REGNUM))
/* Similarly ignore dual loads from the stack. */
/* ADDR must correspond to a symbol whose name is __stack_chk_guard.
Otherwise, this sequence cannot be for stack protector. */
if (stack_chk_guard.minsym == NULL
- || !startswith (MSYMBOL_LINKAGE_NAME (stack_chk_guard.minsym), "__stack_chk_guard"))
+ || !startswith (stack_chk_guard.minsym->linkage_name (), "__stack_chk_guard"))
return pc;
if (is_thumb)
&& (cust == NULL
|| COMPUNIT_PRODUCER (cust) == NULL
|| startswith (COMPUNIT_PRODUCER (cust), "GNU ")
- || startswith (COMPUNIT_PRODUCER (cust), "clang ")))
+ || producer_is_llvm (COMPUNIT_PRODUCER (cust))))
return post_prologue_pc;
if (post_prologue_pc != 0)
struct arm_exidx_entry
{
- bfd_vma addr;
+ CORE_ADDR addr;
gdb_byte *entry;
bool operator< (const arm_exidx_entry &other) const
struct gdbarch *gdbarch = get_frame_arch (this_frame);
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
struct arm_prologue_cache *cache;
+ CORE_ADDR lr;
+ CORE_ADDR sp;
CORE_ADDR unwound_sp;
LONGEST xpsr;
+ uint32_t exc_return;
+ uint32_t process_stack_used;
+ uint32_t extended_frame_used;
+ uint32_t secure_stack_used;
cache = FRAME_OBSTACK_ZALLOC (struct arm_prologue_cache);
cache->saved_regs = trad_frame_alloc_saved_regs (this_frame);
- unwound_sp = get_frame_register_unsigned (this_frame,
- ARM_SP_REGNUM);
+ /* ARMv7-M Architecture Reference "B1.5.6 Exception entry behavior"
+ describes which bits in LR that define which stack was used prior
+ to the exception and if FPU is used (causing extended stack frame). */
+
+ lr = get_frame_register_unsigned (this_frame, ARM_LR_REGNUM);
+ sp = get_frame_register_unsigned (this_frame, ARM_SP_REGNUM);
+
+ /* Check EXC_RETURN indicator bits. */
+ exc_return = (((lr >> 28) & 0xf) == 0xf);
+
+ /* Check EXC_RETURN bit SPSEL if Main or Thread (process) stack used. */
+ process_stack_used = ((lr & (1 << 2)) != 0);
+ if (exc_return && process_stack_used)
+ {
+ /* Thread (process) stack used.
+ Potentially this could be other register defined by target, but PSP
+ can be considered a standard name for the "Process Stack Pointer".
+ To be fully aware of system registers like MSP and PSP, these could
+ be added to a separate XML arm-m-system-profile that is valid for
+ ARMv6-M and ARMv7-M architectures. Also to be able to debug eg a
+ corefile off-line, then these registers must be defined by GDB,
+ and also be included in the corefile regsets. */
+
+ int psp_regnum = user_reg_map_name_to_regnum (gdbarch, "psp", -1);
+ if (psp_regnum == -1)
+ {
+ /* Thread (process) stack could not be fetched,
+ give warning and exit. */
+
+ warning (_("no PSP thread stack unwinding supported."));
+
+ /* Terminate any further stack unwinding by refer to self. */
+ cache->prev_sp = sp;
+ return cache;
+ }
+ else
+ {
+ /* Thread (process) stack used, use PSP as SP. */
+ unwound_sp = get_frame_register_unsigned (this_frame, psp_regnum);
+ }
+ }
+ else
+ {
+ /* Main stack used, use MSP as SP. */
+ unwound_sp = sp;
+ }
/* The hardware saves eight 32-bit words, comprising xPSR,
ReturnAddress, LR (R14), R12, R3, R2, R1, R0. See details in
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[12].addr = unwound_sp + 16;
- cache->saved_regs[14].addr = unwound_sp + 20;
- cache->saved_regs[15].addr = unwound_sp + 24;
+ 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;
+ /* Check EXC_RETURN bit FTYPE if extended stack frame (FPU regs stored)
+ type used. */
+ extended_frame_used = ((lr & (1 << 4)) == 0);
+ if (exc_return && extended_frame_used)
+ {
+ int i;
+ int fpu_regs_stack_offset;
+
+ /* This code does not take into account the lazy stacking, see "Lazy
+ context save of FP state", in B1.5.7, also ARM AN298, supported
+ by Cortex-M4F architecture.
+ To fully handle this the FPCCR register (Floating-point Context
+ Control Register) needs to be read out and the bits ASPEN and LSPEN
+ could be checked to setup correct lazy stacked FP registers.
+ This register is located at address 0xE000EF34. */
+
+ /* Extended stack frame 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;
+ fpu_regs_stack_offset += 4;
+ }
+ cache->saved_regs[ARM_FPSCR_REGNUM].addr = unwound_sp + 0x60;
+
+ /* Offset 0x64 is reserved. */
+ cache->prev_sp = unwound_sp + 0x68;
+ }
+ else
+ {
+ /* Standard stack frame type used. */
+ cache->prev_sp = unwound_sp + 0x20;
+ }
+
+ /* Check EXC_RETURN bit S if Secure or Non-secure stack used. */
+ secure_stack_used = ((lr & (1 << 6)) != 0);
+ if (exc_return && secure_stack_used)
+ {
+ /* ARMv8-M Exception and interrupt handling is not considered here.
+ In the ARMv8-M architecture also EXC_RETURN bit S is controlling if
+ the Secure or Non-secure stack was used. To separate Secure and
+ Non-secure stacks, processors that are based on the ARMv8-M
+ architecture support 4 stack pointers: MSP_S, PSP_S, MSP_NS, PSP_NS.
+ In addition, a stack limit feature is provided using stack limit
+ registers (accessible using MSR and MRS instructions) in Privileged
+ level. */
+ }
+
/* If bit 9 of the saved xPSR is set, then there is a four-byte
aligner between the top of the 32-byte stack frame and the
previous context's stack pointer. */
- cache->prev_sp = unwound_sp + 32;
if (safe_read_memory_integer (unwound_sp + 28, 4, byte_order, &xpsr)
&& (xpsr & (1 << 9)) != 0)
cache->prev_sp += 4;
arm_type_align (gdbarch *gdbarch, struct type *t)
{
t = check_typedef (t);
- if (TYPE_CODE (t) == TYPE_CODE_ARRAY && TYPE_VECTOR (t))
+ if (t->code () == TYPE_CODE_ARRAY && t->is_vector ())
{
/* Use the natural alignment for vector types (the same for
scalar type), but the maximum alignment is 64-bit. */
enum arm_vfp_cprc_base_type *base_type)
{
t = check_typedef (t);
- switch (TYPE_CODE (t))
+ switch (t->code ())
{
case TYPE_CODE_FLT:
switch (TYPE_LENGTH (t))
case TYPE_CODE_ARRAY:
{
- if (TYPE_VECTOR (t))
+ if (t->is_vector ())
{
/* A 64-bit or 128-bit containerized vector type are VFP
CPRCs. */
int count = 0;
unsigned unitlen;
int i;
- for (i = 0; i < TYPE_NFIELDS (t); i++)
+ for (i = 0; i < t->num_fields (); i++)
{
int sub_count = 0;
- if (!field_is_static (&TYPE_FIELD (t, i)))
- sub_count = arm_vfp_cprc_sub_candidate (TYPE_FIELD_TYPE (t, i),
+ if (!field_is_static (&t->field (i)))
+ sub_count = arm_vfp_cprc_sub_candidate (t->field (i).type (),
base_type);
if (sub_count == -1)
return -1;
int count = 0;
unsigned unitlen;
int i;
- for (i = 0; i < TYPE_NFIELDS (t); i++)
+ for (i = 0; i < t->num_fields (); i++)
{
- int sub_count = arm_vfp_cprc_sub_candidate (TYPE_FIELD_TYPE (t, i),
+ int sub_count = arm_vfp_cprc_sub_candidate (t->field (i).type (),
base_type);
if (sub_count == -1)
return -1;
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
/* Variadic functions always use the base ABI. Assume that functions
without debug info are not variadic. */
- if (func_type && TYPE_VARARGS (check_typedef (func_type)))
+ 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)
/* Determine the type of this function and whether the VFP ABI
applies. */
ftype = check_typedef (value_type (function));
- if (TYPE_CODE (ftype) == TYPE_CODE_PTR)
+ if (ftype->code () == TYPE_CODE_PTR)
ftype = check_typedef (TYPE_TARGET_TYPE (ftype));
use_vfp_abi = arm_vfp_abi_for_function (gdbarch, ftype);
arg_type = check_typedef (value_type (args[argnum]));
len = TYPE_LENGTH (arg_type);
target_type = TYPE_TARGET_TYPE (arg_type);
- typecode = TYPE_CODE (arg_type);
+ typecode = arg_type->code ();
val = value_contents (args[argnum]);
align = type_align (arg_type);
the THUMB bit in it. */
if (TYPE_CODE_PTR == typecode
&& target_type != NULL
- && TYPE_CODE_FUNC == TYPE_CODE (check_typedef (target_type)))
+ && TYPE_CODE_FUNC == check_typedef (target_type)->code ())
{
CORE_ADDR regval = extract_unsigned_integer (val, len, byte_order);
if (arm_pc_is_thumb (gdbarch, regval))
elem = builtin_type (gdbarch)->builtin_double;
append_composite_type_field (t, "f64", elem);
- TYPE_VECTOR (t) = 1;
- TYPE_NAME (t) = "neon_d";
+ t->set_is_vector (true);
+ t->set_name ("neon_d");
tdep->neon_double_type = t;
}
elem = builtin_type (gdbarch)->builtin_double;
append_composite_type_field (t, "f64", init_vector_type (elem, 2));
- TYPE_VECTOR (t) = 1;
- TYPE_NAME (t) = "neon_q";
+ t->set_is_vector (true);
+ t->set_name ("neon_q");
tdep->neon_quad_type = t;
}
struct type *t = tdesc_register_type (gdbarch, regnum);
if (regnum >= ARM_D0_REGNUM && regnum < ARM_D0_REGNUM + 32
- && TYPE_CODE (t) == TYPE_CODE_FLT
+ && t->code () == TYPE_CODE_FLT
&& gdbarch_tdep (gdbarch)->have_neon)
return arm_neon_double_type (gdbarch);
else
{
uint32_t status = displaced_read_reg (regs, dsc, ARM_PS_REGNUM);
int store_executed = condition_true (dsc->u.block.cond, status);
- CORE_ADDR pc_stored_at, transferred_regs = bitcount (dsc->u.block.regmask);
+ CORE_ADDR pc_stored_at, transferred_regs
+ = count_one_bits (dsc->u.block.regmask);
CORE_ADDR stm_insn_addr;
uint32_t pc_val;
long offset;
uint32_t status = displaced_read_reg (regs, dsc, ARM_PS_REGNUM);
int load_executed = condition_true (dsc->u.block.cond, status);
unsigned int mask = dsc->u.block.regmask, write_reg = ARM_PC_REGNUM;
- unsigned int regs_loaded = bitcount (mask);
+ unsigned int regs_loaded = count_one_bits (mask);
unsigned int num_to_shuffle = regs_loaded, clobbered;
/* The method employed here will fail if the register list is fully populated
contiguous chunk r0...rX before doing the transfer, then shuffling
registers into the correct places in the cleanup routine. */
unsigned int regmask = insn & 0xffff;
- unsigned int num_in_list = bitcount (regmask), new_regmask;
+ unsigned int num_in_list = count_one_bits (regmask), new_regmask;
unsigned int i;
for (i = 0; i < num_in_list; i++)
else
{
unsigned int regmask = dsc->u.block.regmask;
- unsigned int num_in_list = bitcount (regmask), new_regmask;
+ unsigned int num_in_list = count_one_bits (regmask), new_regmask;
unsigned int i;
for (i = 0; i < num_in_list; i++)
}
else
{
- unsigned int num_in_list = bitcount (dsc->u.block.regmask);
+ unsigned int num_in_list = count_one_bits (dsc->u.block.regmask);
unsigned int i;
unsigned int new_regmask;
struct gdbarch *gdbarch = regs->arch ();
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- if (TYPE_CODE_FLT == TYPE_CODE (type))
+ if (TYPE_CODE_FLT == type->code ())
{
switch (gdbarch_tdep (gdbarch)->fp_model)
{
break;
}
}
- else if (TYPE_CODE (type) == TYPE_CODE_INT
- || TYPE_CODE (type) == TYPE_CODE_CHAR
- || TYPE_CODE (type) == TYPE_CODE_BOOL
- || TYPE_CODE (type) == TYPE_CODE_PTR
+ else if (type->code () == TYPE_CODE_INT
+ || type->code () == TYPE_CODE_CHAR
+ || type->code () == TYPE_CODE_BOOL
+ || type->code () == TYPE_CODE_PTR
|| TYPE_IS_REFERENCE (type)
- || TYPE_CODE (type) == TYPE_CODE_ENUM)
+ || type->code () == TYPE_CODE_ENUM)
{
/* If the type is a plain integer, then the access is
straight-forward. Otherwise we have to play around a bit
/* Simple, non-aggregate types (ie not including vectors and
complex) are always returned in a register (or registers). */
- code = TYPE_CODE (type);
+ code = type->code ();
if (TYPE_CODE_STRUCT != code && TYPE_CODE_UNION != code
&& TYPE_CODE_ARRAY != code && TYPE_CODE_COMPLEX != code)
return 0;
- if (TYPE_CODE_ARRAY == code && TYPE_VECTOR (type))
+ if (TYPE_CODE_ARRAY == code && type->is_vector ())
{
/* Vector values should be returned using ARM registers if they
are not over 16 bytes. */
--> yes, nRc = 1
*/
- for (i = 0; i < TYPE_NFIELDS (type); i++)
+ for (i = 0; i < type->num_fields (); i++)
{
enum type_code field_type_code;
field_type_code
- = TYPE_CODE (check_typedef (TYPE_FIELD_TYPE (type,
- i)));
+ = check_typedef (type->field (i).type ())->code ();
/* Is it a floating point type field? */
if (field_type_code == TYPE_CODE_FLT)
struct gdbarch *gdbarch = regs->arch ();
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- if (TYPE_CODE (type) == TYPE_CODE_FLT)
+ if (type->code () == TYPE_CODE_FLT)
{
gdb_byte buf[ARM_FP_REGISTER_SIZE];
break;
}
}
- else if (TYPE_CODE (type) == TYPE_CODE_INT
- || TYPE_CODE (type) == TYPE_CODE_CHAR
- || TYPE_CODE (type) == TYPE_CODE_BOOL
- || TYPE_CODE (type) == TYPE_CODE_PTR
+ else if (type->code () == TYPE_CODE_INT
+ || type->code () == TYPE_CODE_CHAR
+ || type->code () == TYPE_CODE_BOOL
+ || type->code () == TYPE_CODE_PTR
|| TYPE_IS_REFERENCE (type)
- || TYPE_CODE (type) == TYPE_CODE_ENUM)
+ || type->code () == TYPE_CODE_ENUM)
{
if (TYPE_LENGTH (type) <= 4)
{
return RETURN_VALUE_REGISTER_CONVENTION;
}
- if (TYPE_CODE (valtype) == TYPE_CODE_STRUCT
- || TYPE_CODE (valtype) == TYPE_CODE_UNION
- || TYPE_CODE (valtype) == TYPE_CODE_ARRAY)
+ if (valtype->code () == TYPE_CODE_STRUCT
+ || valtype->code () == TYPE_CODE_UNION
+ || valtype->code () == TYPE_CODE_ARRAY)
{
if (tdep->struct_return == pcc_struct_return
|| arm_return_in_memory (gdbarch, valtype))
return RETURN_VALUE_STRUCT_CONVENTION;
}
- else if (TYPE_CODE (valtype) == TYPE_CODE_COMPLEX)
+ else if (valtype->code () == TYPE_CODE_COMPLEX)
{
if (arm_return_in_memory (gdbarch, valtype))
return RETURN_VALUE_STRUCT_CONVENTION;
return 0; /* not a stub */
}
-static void
-set_arm_command (const char *args, int from_tty)
-{
- printf_unfiltered (_("\
-\"set arm\" must be followed by an apporpriate subcommand.\n"));
- help_list (setarmcmdlist, "set arm ", all_commands, gdb_stdout);
-}
-
-static void
-show_arm_command (const char *args, int from_tty)
-{
- cmd_show_list (showarmcmdlist, from_tty, "");
-}
-
static void
arm_update_current_architecture (void)
{
asymbol *sym)
{
const char *name = bfd_asymbol_name (sym);
- struct arm_per_objfile *data;
+ struct arm_per_bfd *data;
struct arm_mapping_symbol new_map_sym;
gdb_assert (name[0] == '$');
if (name[1] != 'a' && name[1] != 't' && name[1] != 'd')
return;
- data = arm_objfile_data_key.get (objfile);
+ data = arm_bfd_data_key.get (objfile->obfd);
if (data == NULL)
- data = arm_objfile_data_key.emplace (objfile,
- objfile->obfd->section_count);
+ data = arm_bfd_data_key.emplace (objfile->obfd,
+ objfile->obfd->section_count);
arm_mapping_symbol_vec &map
= data->section_maps[bfd_asymbol_section (sym)->index];
if (elfosabi == ELFOSABI_ARM)
/* GNU tools use this value. Check note sections in this case,
as well. */
- bfd_map_over_sections (abfd,
- generic_elf_osabi_sniff_abi_tag_sections,
- &osabi);
+ {
+ for (asection *sect : gdb_bfd_sections (abfd))
+ generic_elf_osabi_sniff_abi_tag_sections (abfd, sect, &osabi);
+ }
/* Anything else will be handled by the generic ELF sniffer. */
return osabi;
struct gdbarch_list *best_arch;
enum arm_abi_kind arm_abi = arm_abi_global;
enum arm_float_model fp_model = arm_fp_model;
- struct tdesc_arch_data *tdesc_data = NULL;
- int i, is_m = 0;
- int vfp_register_count = 0, have_vfp_pseudos = 0, have_neon_pseudos = 0;
- int have_wmmx_registers = 0;
- int have_neon = 0;
- int have_fpa_registers = 1;
+ tdesc_arch_data_up tdesc_data;
+ int i;
+ bool is_m = false;
+ int vfp_register_count = 0;
+ bool have_vfp_pseudos = false, have_neon_pseudos = false;
+ bool have_wmmx_registers = false;
+ bool have_neon = false;
+ bool have_fpa_registers = true;
const struct target_desc *tdesc = info.target_desc;
/* If we have an object to base this architecture on, try to determine
&& (attr_arch == TAG_CPU_ARCH_V6_M
|| attr_arch == TAG_CPU_ARCH_V6S_M
|| attr_profile == 'M'))
- is_m = 1;
+ is_m = true;
#endif
}
if (feature == NULL)
return NULL;
else
- is_m = 1;
+ is_m = true;
}
tdesc_data = tdesc_data_alloc ();
valid_p = 1;
for (i = 0; i < ARM_SP_REGNUM; i++)
- valid_p &= tdesc_numbered_register (feature, tdesc_data, i,
+ valid_p &= tdesc_numbered_register (feature, tdesc_data.get (), i,
arm_register_names[i]);
- valid_p &= tdesc_numbered_register_choices (feature, tdesc_data,
+ valid_p &= tdesc_numbered_register_choices (feature, tdesc_data.get (),
ARM_SP_REGNUM,
arm_sp_names);
- valid_p &= tdesc_numbered_register_choices (feature, tdesc_data,
+ valid_p &= tdesc_numbered_register_choices (feature, tdesc_data.get (),
ARM_LR_REGNUM,
arm_lr_names);
- valid_p &= tdesc_numbered_register_choices (feature, tdesc_data,
+ valid_p &= tdesc_numbered_register_choices (feature, tdesc_data.get (),
ARM_PC_REGNUM,
arm_pc_names);
if (is_m)
- valid_p &= tdesc_numbered_register (feature, tdesc_data,
+ valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
ARM_PS_REGNUM, "xpsr");
else
- valid_p &= tdesc_numbered_register (feature, tdesc_data,
+ valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
ARM_PS_REGNUM, "cpsr");
if (!valid_p)
- {
- tdesc_data_cleanup (tdesc_data);
- return NULL;
- }
+ return NULL;
feature = tdesc_find_feature (tdesc,
"org.gnu.gdb.arm.fpa");
{
valid_p = 1;
for (i = ARM_F0_REGNUM; i <= ARM_FPS_REGNUM; i++)
- valid_p &= tdesc_numbered_register (feature, tdesc_data, i,
+ valid_p &= tdesc_numbered_register (feature, tdesc_data.get (), i,
arm_register_names[i]);
if (!valid_p)
- {
- tdesc_data_cleanup (tdesc_data);
- return NULL;
- }
+ return NULL;
}
else
- have_fpa_registers = 0;
+ have_fpa_registers = false;
feature = tdesc_find_feature (tdesc,
"org.gnu.gdb.xscale.iwmmxt");
valid_p = 1;
for (i = ARM_WR0_REGNUM; i <= ARM_WR15_REGNUM; i++)
valid_p
- &= tdesc_numbered_register (feature, tdesc_data, i,
+ &= tdesc_numbered_register (feature, tdesc_data.get (), i,
iwmmxt_names[i - ARM_WR0_REGNUM]);
/* Check for the control registers, but do not fail if they
are missing. */
for (i = ARM_WC0_REGNUM; i <= ARM_WCASF_REGNUM; i++)
- tdesc_numbered_register (feature, tdesc_data, i,
+ tdesc_numbered_register (feature, tdesc_data.get (), i,
iwmmxt_names[i - ARM_WR0_REGNUM]);
for (i = ARM_WCGR0_REGNUM; i <= ARM_WCGR3_REGNUM; i++)
valid_p
- &= tdesc_numbered_register (feature, tdesc_data, i,
+ &= tdesc_numbered_register (feature, tdesc_data.get (), i,
iwmmxt_names[i - ARM_WR0_REGNUM]);
if (!valid_p)
- {
- tdesc_data_cleanup (tdesc_data);
- return NULL;
- }
+ return NULL;
- have_wmmx_registers = 1;
+ have_wmmx_registers = true;
}
/* If we have a VFP unit, check whether the single precision registers
valid_p = 1;
for (i = 0; i < 32; i++)
{
- valid_p &= tdesc_numbered_register (feature, tdesc_data,
+ valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
ARM_D0_REGNUM + i,
vfp_double_names[i]);
if (!valid_p)
valid_p = 1;
/* Also require FPSCR. */
- valid_p &= tdesc_numbered_register (feature, tdesc_data,
+ valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
ARM_FPSCR_REGNUM, "fpscr");
if (!valid_p)
- {
- tdesc_data_cleanup (tdesc_data);
- return NULL;
- }
+ return NULL;
if (tdesc_unnumbered_register (feature, "s0") == 0)
- have_vfp_pseudos = 1;
+ have_vfp_pseudos = true;
vfp_register_count = i;
{
/* NEON requires 32 double-precision registers. */
if (i != 32)
- {
- tdesc_data_cleanup (tdesc_data);
- return NULL;
- }
+ return NULL;
/* If there are quad registers defined by the stub, use
their type; otherwise (normally) provide them with
the default type. */
if (tdesc_unnumbered_register (feature, "q0") == 0)
- have_neon_pseudos = 1;
+ have_neon_pseudos = true;
- have_neon = 1;
+ have_neon = true;
}
}
}
}
if (best_arch != NULL)
- {
- if (tdesc_data != NULL)
- tdesc_data_cleanup (tdesc_data);
- return best_arch->gdbarch;
- }
+ return best_arch->gdbarch;
tdep = XCNEW (struct gdbarch_tdep);
gdbarch = gdbarch_alloc (&info, tdep);
set_gdbarch_pseudo_register_write (gdbarch, arm_pseudo_write);
}
- if (tdesc_data)
+ if (tdesc_data != nullptr)
{
set_tdesc_pseudo_register_name (gdbarch, arm_register_name);
- tdesc_use_registers (gdbarch, tdesc, tdesc_data);
+ tdesc_use_registers (gdbarch, tdesc, std::move (tdesc_data));
/* Override tdesc_register_type to adjust the types of VFP
registers for NEON. */
if (tdep == NULL)
return;
- fprintf_unfiltered (file, _("arm_dump_tdep: Lowest pc = 0x%lx"),
+ 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);
}
}
#endif
+void _initialize_arm_tdep ();
void
-_initialize_arm_tdep (void)
+_initialize_arm_tdep ()
{
long length;
int i, j;
arm_elf_osabi_sniffer);
/* Add root prefix command for all "set arm"/"show arm" commands. */
- add_prefix_cmd ("arm", no_class, set_arm_command,
- _("Various ARM-specific commands."),
- &setarmcmdlist, "set arm ", 0, &setlist);
+ add_basic_prefix_cmd ("arm", no_class,
+ _("Various ARM-specific commands."),
+ &setarmcmdlist, "set arm ", 0, &setlist);
- add_prefix_cmd ("arm", no_class, show_arm_command,
- _("Various ARM-specific commands."),
- &showarmcmdlist, "show arm ", 0, &showlist);
+ add_show_prefix_cmd ("arm", no_class,
+ _("Various ARM-specific commands."),
+ &showarmcmdlist, "show arm ", 0, &showlist);
arm_disassembler_options = xstrdup ("reg-names-std");