/* Common target dependent code for GDB on ARM systems.
- Copyright (C) 1988-2017 Free Software Foundation, Inc.
+ Copyright (C) 1988-2018 Free Software Foundation, Inc.
This file is part of GDB.
#include "disasm.h"
#include "regcache.h"
#include "reggroups.h"
-#include "doublest.h"
+#include "target-float.h"
#include "value.h"
#include "arch-utils.h"
#include "osabi.h"
#include "remote.h"
#include "target-descriptions.h"
#include "user-regs.h"
-#include "observer.h"
+#include "observable.h"
#include "arch/arm.h"
#include "arch/arm-get-next-pcs.h"
/* This is used to keep the bfd arch_info in sync with the disassembly
style. */
-static void set_disassembly_style_sfunc(char *, int,
+static void set_disassembly_style_sfunc (const char *, int,
struct cmd_list_element *);
static void show_disassembly_style_sfunc (struct ui_file *, int,
struct cmd_list_element *,
const char *);
static enum register_status arm_neon_quad_read (struct gdbarch *gdbarch,
- struct regcache *regcache,
+ readable_regcache *regcache,
int regnum, gdb_byte *buf);
static void arm_neon_quad_write (struct gdbarch *gdbarch,
struct regcache *regcache,
static void
arm_exidx_new_objfile (struct objfile *objfile)
{
- struct cleanup *cleanups;
struct arm_exidx_data *data;
asection *exidx, *extab;
bfd_vma exidx_vma = 0, extab_vma = 0;
- bfd_size_type exidx_size = 0, extab_size = 0;
- gdb_byte *exidx_data = NULL, *extab_data = NULL;
LONGEST i;
/* If we've already touched this file, do nothing. */
if (!objfile || objfile_data (objfile, arm_exidx_data_key) != NULL)
return;
- cleanups = make_cleanup (null_cleanup, NULL);
/* Read contents of exception table and index. */
exidx = bfd_get_section_by_name (objfile->obfd, ELF_STRING_ARM_unwind);
+ gdb::byte_vector exidx_data;
if (exidx)
{
exidx_vma = bfd_section_vma (objfile->obfd, exidx);
- exidx_size = bfd_get_section_size (exidx);
- exidx_data = (gdb_byte *) xmalloc (exidx_size);
- make_cleanup (xfree, exidx_data);
+ exidx_data.resize (bfd_get_section_size (exidx));
if (!bfd_get_section_contents (objfile->obfd, exidx,
- exidx_data, 0, exidx_size))
- {
- do_cleanups (cleanups);
- return;
- }
+ exidx_data.data (), 0,
+ exidx_data.size ()))
+ return;
}
extab = bfd_get_section_by_name (objfile->obfd, ".ARM.extab");
+ gdb::byte_vector extab_data;
if (extab)
{
extab_vma = bfd_section_vma (objfile->obfd, extab);
- extab_size = bfd_get_section_size (extab);
- extab_data = (gdb_byte *) xmalloc (extab_size);
- make_cleanup (xfree, extab_data);
+ extab_data.resize (bfd_get_section_size (extab));
if (!bfd_get_section_contents (objfile->obfd, extab,
- extab_data, 0, extab_size))
- {
- do_cleanups (cleanups);
- return;
- }
+ extab_data.data (), 0,
+ extab_data.size ()))
+ return;
}
/* Allocate exception table data structure. */
VEC(arm_exidx_entry_s) *);
/* Fill in exception table. */
- for (i = 0; i < exidx_size / 8; i++)
+ for (i = 0; i < exidx_data.size () / 8; i++)
{
struct arm_exidx_entry new_exidx_entry;
- bfd_vma idx = bfd_h_get_32 (objfile->obfd, exidx_data + i * 8);
- bfd_vma val = bfd_h_get_32 (objfile->obfd, exidx_data + i * 8 + 4);
+ bfd_vma idx = bfd_h_get_32 (objfile->obfd, exidx_data.data () + i * 8);
+ bfd_vma val = bfd_h_get_32 (objfile->obfd,
+ exidx_data.data () + i * 8 + 4);
bfd_vma addr = 0, word = 0;
int n_bytes = 0, n_words = 0;
struct obj_section *sec;
addr = ((val & 0x7fffffff) ^ 0x40000000) - 0x40000000;
addr += exidx_vma + i * 8 + 4;
- if (addr >= extab_vma && addr + 4 <= extab_vma + extab_size)
+ if (addr >= extab_vma && addr + 4 <= extab_vma + extab_data.size ())
{
word = bfd_h_get_32 (objfile->obfd,
- extab_data + addr - extab_vma);
+ extab_data.data () + addr - extab_vma);
addr += 4;
if ((word & 0xff000000) == 0x80000000)
byte, followed by the same unwind instructions as the
pre-defined forms. */
if (gnu_personality
- && addr + 4 <= extab_vma + extab_size)
+ && addr + 4 <= extab_vma + extab_data.size ())
{
word = bfd_h_get_32 (objfile->obfd,
- extab_data + addr - extab_vma);
+ (extab_data.data ()
+ + addr - extab_vma));
addr += 4;
n_bytes = 3;
n_words = ((word >> 24) & 0xff);
/* Sanity check address. */
if (n_words)
- if (addr < extab_vma || addr + 4 * n_words > extab_vma + extab_size)
+ if (addr < extab_vma
+ || addr + 4 * n_words > extab_vma + extab_data.size ())
n_words = n_bytes = 0;
/* The unwind instructions reside in WORD (only the N_BYTES least
while (n_words--)
{
word = bfd_h_get_32 (objfile->obfd,
- extab_data + addr - extab_vma);
+ extab_data.data () + addr - extab_vma);
addr += 4;
*p++ = (gdb_byte) ((word >> 24) & 0xff);
data->section_maps[sec->the_bfd_section->index],
&new_exidx_entry);
}
-
- do_cleanups (cleanups);
}
/* Search for the exception table entry covering MEMADDR. If one is found,
reg_char, reg_scaled + i);
regnum = user_reg_map_name_to_regnum (gdbarch, name_buf,
strlen (name_buf));
- regcache_cooked_write (regcache, regnum,
- val + i * unit_length);
+ regcache->cooked_write (regnum, val + i * unit_length);
}
}
continue;
else if (op == 0x3)
/* Not really supported. */
return arm_copy_unmodified (gdbarch, insn, "smc", dsc);
+ /* Fall through. */
default:
return arm_copy_undef (gdbarch, insn, dsc);
internal type. */
bfd_byte tmpbuf[FP_REGISTER_SIZE];
- regcache_cooked_read (regs, ARM_F0_REGNUM, tmpbuf);
- convert_typed_floating (tmpbuf, arm_ext_type (gdbarch),
- valbuf, type);
+ regs->cooked_read (ARM_F0_REGNUM, tmpbuf);
+ target_float_convert (tmpbuf, arm_ext_type (gdbarch),
+ valbuf, type);
}
break;
/* ARM_FLOAT_VFP can arise if this is a variadic function so
not using the VFP ABI code. */
case ARM_FLOAT_VFP:
- regcache_cooked_read (regs, ARM_A1_REGNUM, valbuf);
+ regs->cooked_read (ARM_A1_REGNUM, valbuf);
if (TYPE_LENGTH (type) > 4)
- regcache_cooked_read (regs, ARM_A1_REGNUM + 1,
- valbuf + INT_REGISTER_SIZE);
+ regs->cooked_read (ARM_A1_REGNUM + 1, valbuf + INT_REGISTER_SIZE);
break;
default:
while (len > 0)
{
- regcache_cooked_read (regs, regno++, tmpbuf);
+ regs->cooked_read (regno++, tmpbuf);
memcpy (valbuf, tmpbuf,
len > INT_REGISTER_SIZE ? INT_REGISTER_SIZE : len);
len -= INT_REGISTER_SIZE;
{
case ARM_FLOAT_FPA:
- convert_typed_floating (valbuf, type, buf, arm_ext_type (gdbarch));
- regcache_cooked_write (regs, ARM_F0_REGNUM, buf);
+ target_float_convert (valbuf, type, buf, arm_ext_type (gdbarch));
+ regs->cooked_write (ARM_F0_REGNUM, buf);
break;
case ARM_FLOAT_SOFT_FPA:
/* ARM_FLOAT_VFP can arise if this is a variadic function so
not using the VFP ABI code. */
case ARM_FLOAT_VFP:
- regcache_cooked_write (regs, ARM_A1_REGNUM, valbuf);
+ regs->cooked_write (ARM_A1_REGNUM, valbuf);
if (TYPE_LENGTH (type) > 4)
- regcache_cooked_write (regs, ARM_A1_REGNUM + 1,
- valbuf + INT_REGISTER_SIZE);
+ regs->cooked_write (ARM_A1_REGNUM + 1, valbuf + INT_REGISTER_SIZE);
break;
default:
LONGEST val = unpack_long (type, valbuf);
store_signed_integer (tmpbuf, INT_REGISTER_SIZE, byte_order, val);
- regcache_cooked_write (regs, ARM_A1_REGNUM, tmpbuf);
+ regs->cooked_write (ARM_A1_REGNUM, tmpbuf);
}
else
{
while (len > 0)
{
- regcache_cooked_write (regs, regno++, valbuf);
+ regs->cooked_write (regno++, valbuf);
len -= INT_REGISTER_SIZE;
valbuf += INT_REGISTER_SIZE;
}
{
memcpy (tmpbuf, valbuf,
len > INT_REGISTER_SIZE ? INT_REGISTER_SIZE : len);
- regcache_cooked_write (regs, regno++, tmpbuf);
+ regs->cooked_write (regno++, tmpbuf);
len -= INT_REGISTER_SIZE;
valbuf += INT_REGISTER_SIZE;
}
regnum = user_reg_map_name_to_regnum (gdbarch, name_buf,
strlen (name_buf));
if (writebuf)
- regcache_cooked_write (regcache, regnum,
- writebuf + i * unit_length);
+ regcache->cooked_write (regnum, writebuf + i * unit_length);
if (readbuf)
- regcache_cooked_read (regcache, regnum,
- readbuf + i * unit_length);
+ regcache->cooked_read (regnum, readbuf + i * unit_length);
}
}
return RETURN_VALUE_REGISTER_CONVENTION;
}
static void
-set_fp_model_sfunc (char *args, int from_tty,
+set_fp_model_sfunc (const char *args, int from_tty,
struct cmd_list_element *c)
{
int fp_model;
}
static void
-arm_set_abi (char *args, int from_tty,
+arm_set_abi (const char *args, int from_tty,
struct cmd_list_element *c)
{
int arm_abi;
arm disassembly" command, and does that. */
static void
-set_disassembly_style_sfunc (char *args, int from_tty,
+set_disassembly_style_sfunc (const char *args, int from_tty,
struct cmd_list_element *c)
{
/* Convert the short style name into the long style name (eg, reg-names-*)
the quad register, in [0, 15]. */
static enum register_status
-arm_neon_quad_read (struct gdbarch *gdbarch, struct regcache *regcache,
+arm_neon_quad_read (struct gdbarch *gdbarch, readable_regcache *regcache,
int regnum, gdb_byte *buf)
{
char name_buf[4];
else
offset = 0;
- status = regcache_raw_read (regcache, double_regnum, reg_buf);
+ status = regcache->raw_read (double_regnum, reg_buf);
if (status != REG_VALID)
return status;
memcpy (buf + offset, reg_buf, 8);
offset = 8 - offset;
- status = regcache_raw_read (regcache, double_regnum + 1, reg_buf);
+ status = regcache->raw_read (double_regnum + 1, reg_buf);
if (status != REG_VALID)
return status;
memcpy (buf + offset, reg_buf, 8);
}
static enum register_status
-arm_pseudo_read (struct gdbarch *gdbarch, struct regcache *regcache,
+arm_pseudo_read (struct gdbarch *gdbarch, readable_regcache *regcache,
int regnum, gdb_byte *buf)
{
const int num_regs = gdbarch_num_regs (gdbarch);
double_regnum = user_reg_map_name_to_regnum (gdbarch, name_buf,
strlen (name_buf));
- status = regcache_raw_read (regcache, double_regnum, reg_buf);
+ status = regcache->raw_read (double_regnum, reg_buf);
if (status == REG_VALID)
memcpy (buf, reg_buf + offset, 4);
return status;
else
offset = 0;
- regcache_raw_write (regcache, double_regnum, buf + offset);
+ regcache->raw_write (double_regnum, buf + offset);
offset = 8 - offset;
- regcache_raw_write (regcache, double_regnum + 1, buf + offset);
+ regcache->raw_write (double_regnum + 1, buf + offset);
}
static void
double_regnum = user_reg_map_name_to_regnum (gdbarch, name_buf,
strlen (name_buf));
- regcache_raw_read (regcache, double_regnum, reg_buf);
+ regcache->raw_read (double_regnum, reg_buf);
memcpy (reg_buf + offset, buf, 4);
- regcache_raw_write (regcache, double_regnum, reg_buf);
+ regcache->raw_write (double_regnum, reg_buf);
}
}
else if (ei_osabi == ELFOSABI_NONE || ei_osabi == ELFOSABI_GNU)
{
int eabi_ver = EF_ARM_EABI_VERSION (e_flags);
- int attr_arch, attr_profile;
switch (eabi_ver)
{
executable file includes build attributes; GCC does
copy them to the executable, but e.g. RealView does
not. */
- attr_arch = bfd_elf_get_obj_attr_int (info.abfd, OBJ_ATTR_PROC,
- Tag_CPU_arch);
- attr_profile = bfd_elf_get_obj_attr_int (info.abfd,
- OBJ_ATTR_PROC,
- Tag_CPU_arch_profile);
+ int attr_arch
+ = bfd_elf_get_obj_attr_int (info.abfd, OBJ_ATTR_PROC,
+ Tag_CPU_arch);
+ int attr_profile
+ = bfd_elf_get_obj_attr_int (info.abfd, OBJ_ATTR_PROC,
+ Tag_CPU_arch_profile);
+
/* GCC specifies the profile for v6-M; RealView only
specifies the profile for architectures starting with
V7 (as opposed to architectures with a tag
_initialize_arm_tdep (void)
{
long length;
- const char *setname;
- const char *setdesc;
int i, j;
char regdesc[1024], *rdptr = regdesc;
size_t rest = sizeof (regdesc);
= register_objfile_data_with_cleanup (NULL, arm_objfile_data_free);
/* Add ourselves to objfile event chain. */
- observer_attach_new_objfile (arm_exidx_new_objfile);
+ gdb::observers::new_objfile.attach (arm_exidx_new_objfile);
arm_exidx_data_key
= register_objfile_data_with_cleanup (NULL, arm_exidx_data_free);
arm_disassembler_options = xstrdup ("reg-names-std");
- const disasm_options_t *disasm_options = disassembler_options_arm ();
+ 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-"))
static int
arm_record_extension_space (insn_decode_record *arm_insn_r)
{
- uint32_t ret = 0; /* Return value: -1:record failure ; 0:success */
+ int ret = 0; /* Return value: -1:record failure ; 0:success */
uint32_t opcode1 = 0, opcode2 = 0, insn_op1 = 0;
uint32_t record_buf[8], record_buf_mem[8];
uint32_t reg_src1 = 0;
&& !INSN_RECORDED(arm_insn_r))
{
/* Handle MLA(S) and MUL(S). */
- if (0 <= insn_op1 && 3 >= insn_op1)
+ 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;
}
- else if (4 <= insn_op1 && 15 >= insn_op1)
+ 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);
uint32_t record_buf[8], record_buf_mem[8];
ULONGEST u_regval[2] = {0};
- uint32_t reg_src1 = 0, reg_dest = 0;
+ uint32_t reg_src1 = 0;
uint32_t opcode1 = 0;
arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
- /* Data processing insn /multiply insn. */
- if (9 == arm_insn_r->decode
- && ((4 <= arm_insn_r->opcode && 7 >= arm_insn_r->opcode)
- || (0 == arm_insn_r->opcode || 1 == arm_insn_r->opcode)))
+ if (!((opcode1 & 0x19) == 0x10))
{
- /* 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;
- }
+ /* Data-processing (register) and Data-processing (register-shifted
+ register */
+ /* Out of 11 shifter operands mode, all the insn modifies destination
+ register, which is specified by 13-16 decode. */
+ 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 (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
- && (11 == arm_insn_r->decode || 13 == arm_insn_r->decode))
+ else if ((arm_insn_r->decode < 8) && ((opcode1 & 0x19) == 0x10))
{
- /* Handle misc load insns, as 20th bit (L = 1). */
- /* LDR insn has a capability to do branching, if
- MOV LR, PC is precceded by LDR insn having Rn as R15
- in that case, it emulates branch and link insn, and hence we
- need to save CSPR and PC as well. I am not sure this is right
- place; as opcode = 010 LDR insn make this happen, if R15 was
- used. */
- reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
- if (15 != reg_dest)
- {
- record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
- arm_insn_r->reg_rec_count = 1;
- }
- else
- {
- record_buf[0] = reg_dest;
- record_buf[1] = ARM_PS_REGNUM;
- arm_insn_r->reg_rec_count = 2;
- }
+ /* Miscellaneous instructions */
+
+ if (3 == arm_insn_r->decode && 0x12 == opcode1
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
+ {
+ /* Handle BLX, branch and link/exchange. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm,
+ and R14 stores the return address. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else if (7 == arm_insn_r->decode && 0x12 == opcode1)
+ {
+ /* Handle enhanced software breakpoint insn, BKPT. */
+ /* CPSR is changed to be executed in ARM state, disabling normal
+ interrupts, entering abort mode. */
+ /* According to high vector configuration PC is set. */
+ /* user hit breakpoint and type reverse, in
+ that case, we need to go back with previous CPSR and
+ Program Counter. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+
+ /* Save SPSR also; how? */
+ return -1;
+ }
+ else if (1 == arm_insn_r->decode && 0x12 == opcode1
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
+ {
+ /* Handle BX, branch and link/exchange. */
+ /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == arm_insn_r->decode && 0x16 == opcode1
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 4, 1)
+ && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1))
+ {
+ /* Count leading zeros: CLZ. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (!bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
+ && (8 == arm_insn_r->opcode || 10 == arm_insn_r->opcode)
+ && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1)
+ && sbo_sbz (arm_insn_r->arm_insn, 1, 12, 0))
+ {
+ /* Handle MRS insn. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
}
- else if ((9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode)
- && sbo_sbz (arm_insn_r->arm_insn, 5, 12, 0)
- && sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1)
- && 2 == bits (arm_insn_r->arm_insn, 20, 21))
+ else if (9 == arm_insn_r->decode && opcode1 < 0x10)
{
- /* Handle MSR insn. */
- if (9 == arm_insn_r->opcode)
- {
- /* CSPR is going to be changed. */
- record_buf[0] = ARM_PS_REGNUM;
- arm_insn_r->reg_rec_count = 1;
- }
- else
- {
- /* SPSR is going to be changed. */
- /* How to read SPSR value? */
- return -1;
- }
+ /* Multiply and multiply-accumulate */
+
+ /* 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;
+ }
}
- else if (9 == arm_insn_r->decode
- && (8 == arm_insn_r->opcode || 10 == arm_insn_r->opcode)
- && !bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ else if (9 == arm_insn_r->decode && opcode1 > 0x10)
{
+ /* Synchronization primitives */
+
/* Handling SWP, SWPB. */
/* These insn, changes register and memory as well. */
/* SWP or SWPB insn. */
regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
/* SWP insn ?, swaps word. */
if (8 == arm_insn_r->opcode)
- {
- record_buf_mem[0] = 4;
- }
- else
- {
- /* SWPB insn, swaps only byte. */
- record_buf_mem[0] = 1;
- }
+ {
+ record_buf_mem[0] = 4;
+ }
+ else
+ {
+ /* SWPB insn, swaps only byte. */
+ record_buf_mem[0] = 1;
+ }
record_buf_mem[1] = u_regval[0];
arm_insn_r->mem_rec_count = 1;
record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
arm_insn_r->reg_rec_count = 1;
}
- else if (3 == arm_insn_r->decode && 0x12 == opcode1
- && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
+ else if (11 == arm_insn_r->decode || 13 == arm_insn_r->decode
+ || 15 == arm_insn_r->decode)
{
- /* Handle BLX, branch and link/exchange. */
- if (9 == arm_insn_r->opcode)
- {
- /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm,
- and R14 stores the return address. */
- record_buf[0] = ARM_PS_REGNUM;
- record_buf[1] = ARM_LR_REGNUM;
- arm_insn_r->reg_rec_count = 2;
- }
- }
- else if (7 == arm_insn_r->decode && 0x12 == opcode1)
- {
- /* Handle enhanced software breakpoint insn, BKPT. */
- /* CPSR is changed to be executed in ARM state, disabling normal
- interrupts, entering abort mode. */
- /* According to high vector configuration PC is set. */
- /* user hit breakpoint and type reverse, in
- that case, we need to go back with previous CPSR and
- Program Counter. */
- record_buf[0] = ARM_PS_REGNUM;
- record_buf[1] = ARM_LR_REGNUM;
- arm_insn_r->reg_rec_count = 2;
+ if ((opcode1 & 0x12) == 2)
+ {
+ /* Extra load/store (unprivileged) */
+ return -1;
+ }
+ else
+ {
+ /* Extra load/store */
+ switch (bits (arm_insn_r->arm_insn, 5, 6))
+ {
+ case 1:
+ if ((opcode1 & 0x05) == 0x0 || (opcode1 & 0x05) == 0x4)
+ {
+ /* STRH (register), STRH (immediate) */
+ arm_record_strx (arm_insn_r, &record_buf[0],
+ &record_buf_mem[0], ARM_RECORD_STRH);
+ }
+ else if ((opcode1 & 0x05) == 0x1)
+ {
+ /* LDRH (register) */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
- /* Save SPSR also; how? */
- return -1;
- }
- else if (11 == arm_insn_r->decode
- && !bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
- {
- /* Handle enhanced store insns and DSP insns (e.g. LDRD). */
+ if (bit (arm_insn_r->arm_insn, 21))
+ {
+ /* Write back to Rn. */
+ record_buf[arm_insn_r->reg_rec_count++]
+ = bits (arm_insn_r->arm_insn, 16, 19);
+ }
+ }
+ else if ((opcode1 & 0x05) == 0x5)
+ {
+ /* LDRH (immediate), LDRH (literal) */
+ int rn = bits (arm_insn_r->arm_insn, 16, 19);
- /* Handle str(x) insn */
- arm_record_strx(arm_insn_r, &record_buf[0], &record_buf_mem[0],
- ARM_RECORD_STRH);
- }
- else if (1 == arm_insn_r->decode && 0x12 == opcode1
- && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
- {
- /* Handle BX, branch and link/exchange. */
- /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm. */
- record_buf[0] = ARM_PS_REGNUM;
- arm_insn_r->reg_rec_count = 1;
- }
- else if (1 == arm_insn_r->decode && 0x16 == opcode1
- && sbo_sbz (arm_insn_r->arm_insn, 9, 4, 1)
- && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1))
- {
- /* Count leading zeros: CLZ. */
- record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
- arm_insn_r->reg_rec_count = 1;
- }
- else if (!bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
- && (8 == arm_insn_r->opcode || 10 == arm_insn_r->opcode)
- && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1)
- && sbo_sbz (arm_insn_r->arm_insn, 1, 12, 0)
- )
- {
- /* Handle MRS insn. */
- record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
- arm_insn_r->reg_rec_count = 1;
- }
- else if (arm_insn_r->opcode <= 15)
- {
- /* Normal data processing insns. */
- /* Out of 11 shifter operands mode, all the insn modifies destination
- register, which is specified by 13-16 decode. */
- 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);
+ arm_insn_r->reg_rec_count = 1;
+
+ if (rn != 15)
+ {
+ /*LDRH (immediate) */
+ if (bit (arm_insn_r->arm_insn, 21))
+ {
+ /* Write back to Rn. */
+ record_buf[arm_insn_r->reg_rec_count++] = rn;
+ }
+ }
+ }
+ else
+ return -1;
+ break;
+ case 2:
+ if ((opcode1 & 0x05) == 0x0)
+ {
+ /* LDRD (register) */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = record_buf[0] + 1;
+ arm_insn_r->reg_rec_count = 2;
+
+ if (bit (arm_insn_r->arm_insn, 21))
+ {
+ /* Write back to Rn. */
+ record_buf[arm_insn_r->reg_rec_count++]
+ = bits (arm_insn_r->arm_insn, 16, 19);
+ }
+ }
+ else if ((opcode1 & 0x05) == 0x1)
+ {
+ /* LDRSB (register) */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+
+ if (bit (arm_insn_r->arm_insn, 21))
+ {
+ /* Write back to Rn. */
+ record_buf[arm_insn_r->reg_rec_count++]
+ = bits (arm_insn_r->arm_insn, 16, 19);
+ }
+ }
+ else if ((opcode1 & 0x05) == 0x4 || (opcode1 & 0x05) == 0x5)
+ {
+ /* LDRD (immediate), LDRD (literal), LDRSB (immediate),
+ LDRSB (literal) */
+ int rn = bits (arm_insn_r->arm_insn, 16, 19);
+
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+
+ if (rn != 15)
+ {
+ /*LDRD (immediate), LDRSB (immediate) */
+ if (bit (arm_insn_r->arm_insn, 21))
+ {
+ /* Write back to Rn. */
+ record_buf[arm_insn_r->reg_rec_count++] = rn;
+ }
+ }
+ }
+ else
+ return -1;
+ break;
+ case 3:
+ if ((opcode1 & 0x05) == 0x0)
+ {
+ /* STRD (register) */
+ arm_record_strx (arm_insn_r, &record_buf[0],
+ &record_buf_mem[0], ARM_RECORD_STRD);
+ }
+ else if ((opcode1 & 0x05) == 0x1)
+ {
+ /* LDRSH (register) */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+
+ if (bit (arm_insn_r->arm_insn, 21))
+ {
+ /* Write back to Rn. */
+ record_buf[arm_insn_r->reg_rec_count++]
+ = bits (arm_insn_r->arm_insn, 16, 19);
+ }
+ }
+ else if ((opcode1 & 0x05) == 0x4)
+ {
+ /* STRD (immediate) */
+ arm_record_strx (arm_insn_r, &record_buf[0],
+ &record_buf_mem[0], ARM_RECORD_STRD);
+ }
+ else if ((opcode1 & 0x05) == 0x5)
+ {
+ /* LDRSH (immediate), LDRSH (literal) */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+
+ if (bit (arm_insn_r->arm_insn, 21))
+ {
+ /* Write back to Rn. */
+ record_buf[arm_insn_r->reg_rec_count++]
+ = bits (arm_insn_r->arm_insn, 16, 19);
+ }
+ }
+ else
+ return -1;
+ break;
+ default:
+ return -1;
+ }
+ }
}
else
{
opc3 = bits (arm_insn_r->arm_insn, 6, 7);
dp_op_sz = bit (arm_insn_r->arm_insn, 8);
bit_d = bit (arm_insn_r->arm_insn, 22);
- opc1 = opc1 & 0x04;
+ /* Mask off the "D" bit. */
+ opc1 = opc1 & ~0x04;
/* Handle VMLA, VMLS. */
if (opc1 == 0x00)
}
}
/* Handle VDIV. */
- else if (opc1 == 0x0b)
+ else if (opc1 == 0x08)
{
if (dp_op_sz)
curr_insn_type = INSN_T1;
static int
arm_record_coproc_data_proc (insn_decode_record *arm_insn_r)
{
- uint32_t op, op1_sbit, op1_ebit, coproc;
+ uint32_t op, op1_ebit, coproc, bits_24_25;
struct gdbarch_tdep *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);
coproc = bits (arm_insn_r->arm_insn, 8, 11);
- op1_sbit = bit (arm_insn_r->arm_insn, 24);
op1_ebit = bit (arm_insn_r->arm_insn, 20);
op = bit (arm_insn_r->arm_insn, 4);
+ bits_24_25 = bits (arm_insn_r->arm_insn, 24, 25);
/* Handle arm SWI/SVC system call instructions. */
- if (op1_sbit)
+ if (bits_24_25 == 0x3)
{
if (tdep->arm_syscall_record != NULL)
{
return -1;
}
}
-
- if ((coproc & 0x0e) == 0x0a)
+ else if (bits_24_25 == 0x02)
{
- /* VFP data-processing instructions. */
- if (!op1_sbit && !op)
- return arm_record_vfp_data_proc_insn (arm_insn_r);
+ if (op)
+ {
+ if ((coproc & 0x0e) == 0x0a)
+ {
+ /* 8, 16, and 32-bit transfer */
+ return arm_record_vdata_transfer_insn (arm_insn_r);
+ }
+ else
+ {
+ if (op1_ebit)
+ {
+ /* MRC, MRC2 */
+ uint32_t record_buf[1];
- /* Advanced SIMD, VFP instructions. */
- if (!op1_sbit && op)
- return arm_record_vdata_transfer_insn (arm_insn_r);
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ if (record_buf[0] == 15)
+ record_buf[0] = ARM_PS_REGNUM;
+
+ arm_insn_r->reg_rec_count = 1;
+ REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count,
+ record_buf);
+ return 0;
+ }
+ else
+ {
+ /* MCR, MCR2 */
+ return -1;
+ }
+ }
+ }
+ else
+ {
+ if ((coproc & 0x0e) == 0x0a)
+ {
+ /* VFP data-processing instructions. */
+ return arm_record_vfp_data_proc_insn (arm_insn_r);
+ }
+ else
+ {
+ /* CDP, CDP2 */
+ return -1;
+ }
+ }
}
else
{
- /* Coprocessor data operations. */
- if (!op1_sbit && !op)
- return arm_record_unsupported_insn (arm_insn_r);
-
- /* Move to Coprocessor from ARM core register. */
- if (!op1_sbit && !op1_ebit && op)
- return arm_record_unsupported_insn (arm_insn_r);
-
- /* Move to arm core register from coprocessor. */
- if (!op1_sbit && op1_ebit && op)
- {
- uint32_t record_buf[1];
+ unsigned int op1 = bits (arm_insn_r->arm_insn, 20, 25);
- record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
- if (record_buf[0] == 15)
- record_buf[0] = ARM_PS_REGNUM;
-
- arm_insn_r->reg_rec_count = 1;
- REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count,
- record_buf);
- return 0;
- }
+ if (op1 == 5)
+ {
+ if ((coproc & 0x0e) != 0x0a)
+ {
+ /* MRRC, MRRC2 */
+ return -1;
+ }
+ }
+ else if (op1 == 4 || op1 == 5)
+ {
+ if ((coproc & 0x0e) == 0x0a)
+ {
+ /* 64-bit transfers between ARM core and extension */
+ return -1;
+ }
+ else if (op1 == 4)
+ {
+ /* MCRR, MCRR2 */
+ return -1;
+ }
+ }
+ else if (op1 == 0 || op1 == 1)
+ {
+ /* UNDEFINED */
+ return -1;
+ }
+ else
+ {
+ if ((coproc & 0x0e) == 0x0a)
+ {
+ /* Extension register load/store */
+ }
+ else
+ {
+ /* STC, STC2, LDC, LDC2 */
+ }
+ return -1;
+ }
}
- return arm_record_unsupported_insn (arm_insn_r);
+ return -1;
}
/* Handling opcode 000 insns. */
/* Handle load/store register offset. */
uint32_t opB = bits (thumb_insn_r->arm_insn, 9, 11);
- if (opB >= 4 && opB <= 7)
+ if (in_inclusive_range (opB, 4U, 7U))
{
/* LDR(2), LDRB(2) , LDRH(2), LDRSB, LDRSH. */
reg_src1 = bits (thumb_insn_r->arm_insn,0, 2);
record_buf[0] = reg_src1;
thumb_insn_r->reg_rec_count = 1;
}
- else if (opB >= 0 && opB <= 2)
+ else if (in_inclusive_range (opB, 0U, 2U))
{
/* STR(2), STRB(2), STRH(2) . */
reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
class instruction_reader : public abstract_memory_reader
{
public:
- bool read (CORE_ADDR memaddr, gdb_byte *buf, const size_t len)
+ bool read (CORE_ADDR memaddr, gdb_byte *buf, const size_t len) override
{
if (target_read_memory (memaddr, buf, len))
return false;
: m_endian (endian), m_insns (insns), m_insns_size (SIZE)
{}
- bool read (CORE_ADDR memaddr, gdb_byte *buf, const size_t len)
+ bool read (CORE_ADDR memaddr, gdb_byte *buf, const size_t len) override
{
SELF_CHECK (len == 4 || len == 2);
SELF_CHECK (memaddr % 2 == 0);