/* NOP instruction (mov r0, r0). */
#define ARM_NOP 0xe1a00000
-static int displaced_in_arm_mode (struct regcache *regs);
-
/* Helper for register reads for displaced stepping. In particular, this
returns the PC as it would be seen by the instruction at its original
location. */
ULONGEST
-displaced_read_reg (struct regcache *regs, CORE_ADDR from, int regno)
+displaced_read_reg (struct regcache *regs, struct displaced_step_closure *dsc,
+ int regno)
{
ULONGEST ret;
+ CORE_ADDR from = dsc->insn_addr;
if (regno == ARM_PC_REGNUM)
{
- When executing a Thumb instruction, PC reads as the address of the
current instruction plus 4. */
- if (displaced_in_arm_mode (regs))
+ if (!dsc->is_thumb)
from += 8;
else
from += 4;
/* Write to the PC as from a branch instruction. */
static void
-branch_write_pc (struct regcache *regs, ULONGEST val)
+branch_write_pc (struct regcache *regs, struct displaced_step_closure *dsc,
+ ULONGEST val)
{
- if (displaced_in_arm_mode (regs))
+ if (!dsc->is_thumb)
/* Note: If bits 0/1 are set, this branch would be unpredictable for
architecture versions < 6. */
regcache_cooked_write_unsigned (regs, ARM_PC_REGNUM,
/* Write to the PC as if from a load instruction. */
static void
-load_write_pc (struct regcache *regs, ULONGEST val)
+load_write_pc (struct regcache *regs, struct displaced_step_closure *dsc,
+ ULONGEST val)
{
if (DISPLACED_STEPPING_ARCH_VERSION >= 5)
bx_write_pc (regs, val);
else
- branch_write_pc (regs, val);
+ branch_write_pc (regs, dsc, val);
}
/* Write to the PC as if from an ALU instruction. */
static void
-alu_write_pc (struct regcache *regs, ULONGEST val)
+alu_write_pc (struct regcache *regs, struct displaced_step_closure *dsc,
+ ULONGEST val)
{
- if (DISPLACED_STEPPING_ARCH_VERSION >= 7 && displaced_in_arm_mode (regs))
+ if (DISPLACED_STEPPING_ARCH_VERSION >= 7 && !dsc->is_thumb)
bx_write_pc (regs, val);
else
- branch_write_pc (regs, val);
+ branch_write_pc (regs, dsc, val);
}
/* Helper for writing to registers for displaced stepping. Writing to the PC
switch (write_pc)
{
case BRANCH_WRITE_PC:
- branch_write_pc (regs, val);
+ branch_write_pc (regs, dsc, val);
break;
case BX_WRITE_PC:
break;
case LOAD_WRITE_PC:
- load_write_pc (regs, val);
+ load_write_pc (regs, dsc, val);
break;
case ALU_WRITE_PC:
- alu_write_pc (regs, val);
+ alu_write_pc (regs, dsc, val);
break;
case CANNOT_WRITE_PC:
{
unsigned int rn = bits (insn, 16, 19);
ULONGEST rn_val;
- CORE_ADDR from = dsc->insn_addr;
if (!insn_references_pc (insn, 0x000f0000ul))
return copy_unmodified (gdbarch, insn, "preload", dsc);
->
{pli/pld} [r0, #+/-imm]. */
- dsc->tmp[0] = displaced_read_reg (regs, from, 0);
- rn_val = displaced_read_reg (regs, from, rn);
+ dsc->tmp[0] = displaced_read_reg (regs, dsc, 0);
+ rn_val = displaced_read_reg (regs, dsc, rn);
displaced_write_reg (regs, dsc, 0, rn_val, CANNOT_WRITE_PC);
dsc->u.preload.immed = 1;
unsigned int rn = bits (insn, 16, 19);
unsigned int rm = bits (insn, 0, 3);
ULONGEST rn_val, rm_val;
- CORE_ADDR from = dsc->insn_addr;
if (!insn_references_pc (insn, 0x000f000ful))
return copy_unmodified (gdbarch, insn, "preload reg", dsc);
->
{pli/pld} [r0, r1 {, shift}]. */
- dsc->tmp[0] = displaced_read_reg (regs, from, 0);
- dsc->tmp[1] = displaced_read_reg (regs, from, 1);
- rn_val = displaced_read_reg (regs, from, rn);
- rm_val = displaced_read_reg (regs, from, rm);
+ dsc->tmp[0] = displaced_read_reg (regs, dsc, 0);
+ dsc->tmp[1] = displaced_read_reg (regs, dsc, 1);
+ rn_val = displaced_read_reg (regs, dsc, rn);
+ rm_val = displaced_read_reg (regs, dsc, rm);
displaced_write_reg (regs, dsc, 0, rn_val, CANNOT_WRITE_PC);
displaced_write_reg (regs, dsc, 1, rm_val, CANNOT_WRITE_PC);
struct regcache *regs,
struct displaced_step_closure *dsc)
{
- ULONGEST rn_val = displaced_read_reg (regs, dsc->insn_addr, 0);
+ ULONGEST rn_val = displaced_read_reg (regs, dsc, 0);
displaced_write_reg (regs, dsc, 0, dsc->tmp[0], CANNOT_WRITE_PC);
{
unsigned int rn = bits (insn, 16, 19);
ULONGEST rn_val;
- CORE_ADDR from = dsc->insn_addr;
if (!insn_references_pc (insn, 0x000f0000ul))
return copy_unmodified (gdbarch, insn, "copro load/store", dsc);
ldc/ldc2 are handled identically. */
- dsc->tmp[0] = displaced_read_reg (regs, from, 0);
- rn_val = displaced_read_reg (regs, from, rn);
+ dsc->tmp[0] = displaced_read_reg (regs, dsc, 0);
+ rn_val = displaced_read_reg (regs, dsc, rn);
displaced_write_reg (regs, dsc, 0, rn_val, CANNOT_WRITE_PC);
dsc->u.ldst.writeback = bit (insn, 25);
cleanup_branch (struct gdbarch *gdbarch, struct regcache *regs,
struct displaced_step_closure *dsc)
{
- ULONGEST from = dsc->insn_addr;
- uint32_t status = displaced_read_reg (regs, from, ARM_PS_REGNUM);
+ uint32_t status = displaced_read_reg (regs, dsc, ARM_PS_REGNUM);
int branch_taken = condition_true (dsc->u.branch.cond, status);
enum pc_write_style write_pc = dsc->u.branch.exchange
? BX_WRITE_PC : BRANCH_WRITE_PC;
if (dsc->u.branch.link)
{
- ULONGEST pc = displaced_read_reg (regs, from, ARM_PC_REGNUM);
+ ULONGEST pc = displaced_read_reg (regs, dsc, ARM_PC_REGNUM);
displaced_write_reg (regs, dsc, ARM_LR_REGNUM, pc - 4, CANNOT_WRITE_PC);
}
BLX: x12xxx3x. */
int link = bit (insn, 5);
unsigned int rm = bits (insn, 0, 3);
- CORE_ADDR from = dsc->insn_addr;
if (debug_displaced)
fprintf_unfiltered (gdb_stdlog, "displaced: copying %s register insn "
Don't set r14 in cleanup for BX. */
- dsc->u.branch.dest = displaced_read_reg (regs, from, rm);
+ dsc->u.branch.dest = displaced_read_reg (regs, dsc, rm);
dsc->u.branch.cond = cond;
dsc->u.branch.link = link;
cleanup_alu_imm (struct gdbarch *gdbarch,
struct regcache *regs, struct displaced_step_closure *dsc)
{
- ULONGEST rd_val = displaced_read_reg (regs, dsc->insn_addr, 0);
+ ULONGEST rd_val = displaced_read_reg (regs, dsc, 0);
displaced_write_reg (regs, dsc, 0, dsc->tmp[0], CANNOT_WRITE_PC);
displaced_write_reg (regs, dsc, 1, dsc->tmp[1], CANNOT_WRITE_PC);
displaced_write_reg (regs, dsc, dsc->rd, rd_val, ALU_WRITE_PC);
unsigned int op = bits (insn, 21, 24);
int is_mov = (op == 0xd);
ULONGEST rd_val, rn_val;
- CORE_ADDR from = dsc->insn_addr;
if (!insn_references_pc (insn, 0x000ff000ul))
return copy_unmodified (gdbarch, insn, "ALU immediate", dsc);
Cleanup: rd <- r0; r0 <- tmp1; r1 <- tmp2
*/
- dsc->tmp[0] = displaced_read_reg (regs, from, 0);
- dsc->tmp[1] = displaced_read_reg (regs, from, 1);
- rn_val = displaced_read_reg (regs, from, rn);
- rd_val = displaced_read_reg (regs, from, rd);
+ dsc->tmp[0] = displaced_read_reg (regs, dsc, 0);
+ dsc->tmp[1] = displaced_read_reg (regs, dsc, 1);
+ rn_val = displaced_read_reg (regs, dsc, rn);
+ rd_val = displaced_read_reg (regs, dsc, rd);
displaced_write_reg (regs, dsc, 0, rd_val, CANNOT_WRITE_PC);
displaced_write_reg (regs, dsc, 1, rn_val, CANNOT_WRITE_PC);
dsc->rd = rd;
ULONGEST rd_val;
int i;
- rd_val = displaced_read_reg (regs, dsc->insn_addr, 0);
+ rd_val = displaced_read_reg (regs, dsc, 0);
for (i = 0; i < 3; i++)
displaced_write_reg (regs, dsc, i, dsc->tmp[i], CANNOT_WRITE_PC);
unsigned int op = bits (insn, 21, 24);
int is_mov = (op == 0xd);
ULONGEST rd_val, rn_val, rm_val;
- CORE_ADDR from = dsc->insn_addr;
if (!insn_references_pc (insn, 0x000ff00ful))
return copy_unmodified (gdbarch, insn, "ALU reg", dsc);
Cleanup: rd <- r0; r0, r1, r2 <- tmp1, tmp2, tmp3
*/
- dsc->tmp[0] = displaced_read_reg (regs, from, 0);
- dsc->tmp[1] = displaced_read_reg (regs, from, 1);
- dsc->tmp[2] = displaced_read_reg (regs, from, 2);
- rd_val = displaced_read_reg (regs, from, rd);
- rn_val = displaced_read_reg (regs, from, rn);
- rm_val = displaced_read_reg (regs, from, rm);
+ dsc->tmp[0] = displaced_read_reg (regs, dsc, 0);
+ dsc->tmp[1] = displaced_read_reg (regs, dsc, 1);
+ dsc->tmp[2] = displaced_read_reg (regs, dsc, 2);
+ rd_val = displaced_read_reg (regs, dsc, rd);
+ rn_val = displaced_read_reg (regs, dsc, rn);
+ rm_val = displaced_read_reg (regs, dsc, rm);
displaced_write_reg (regs, dsc, 0, rd_val, CANNOT_WRITE_PC);
displaced_write_reg (regs, dsc, 1, rn_val, CANNOT_WRITE_PC);
displaced_write_reg (regs, dsc, 2, rm_val, CANNOT_WRITE_PC);
struct regcache *regs,
struct displaced_step_closure *dsc)
{
- ULONGEST rd_val = displaced_read_reg (regs, dsc->insn_addr, 0);
+ ULONGEST rd_val = displaced_read_reg (regs, dsc, 0);
int i;
for (i = 0; i < 4; i++)
unsigned int op = bits (insn, 21, 24);
int is_mov = (op == 0xd), i;
ULONGEST rd_val, rn_val, rm_val, rs_val;
- CORE_ADDR from = dsc->insn_addr;
if (!insn_references_pc (insn, 0x000fff0ful))
return copy_unmodified (gdbarch, insn, "ALU shifted reg", dsc);
*/
for (i = 0; i < 4; i++)
- dsc->tmp[i] = displaced_read_reg (regs, from, i);
+ dsc->tmp[i] = displaced_read_reg (regs, dsc, i);
- rd_val = displaced_read_reg (regs, from, rd);
- rn_val = displaced_read_reg (regs, from, rn);
- rm_val = displaced_read_reg (regs, from, rm);
- rs_val = displaced_read_reg (regs, from, rs);
+ rd_val = displaced_read_reg (regs, dsc, rd);
+ rn_val = displaced_read_reg (regs, dsc, rn);
+ rm_val = displaced_read_reg (regs, dsc, rm);
+ rs_val = displaced_read_reg (regs, dsc, rs);
displaced_write_reg (regs, dsc, 0, rd_val, CANNOT_WRITE_PC);
displaced_write_reg (regs, dsc, 1, rn_val, CANNOT_WRITE_PC);
displaced_write_reg (regs, dsc, 2, rm_val, CANNOT_WRITE_PC);
struct displaced_step_closure *dsc)
{
ULONGEST rt_val, rt_val2 = 0, rn_val;
- CORE_ADDR from = dsc->insn_addr;
- rt_val = displaced_read_reg (regs, from, 0);
+ rt_val = displaced_read_reg (regs, dsc, 0);
if (dsc->u.ldst.xfersize == 8)
- rt_val2 = displaced_read_reg (regs, from, 1);
- rn_val = displaced_read_reg (regs, from, 2);
+ rt_val2 = displaced_read_reg (regs, dsc, 1);
+ rn_val = displaced_read_reg (regs, dsc, 2);
displaced_write_reg (regs, dsc, 0, dsc->tmp[0], CANNOT_WRITE_PC);
if (dsc->u.ldst.xfersize > 4)
cleanup_store (struct gdbarch *gdbarch, struct regcache *regs,
struct displaced_step_closure *dsc)
{
- CORE_ADDR from = dsc->insn_addr;
- ULONGEST rn_val = displaced_read_reg (regs, from, 2);
+ ULONGEST rn_val = displaced_read_reg (regs, dsc, 2);
displaced_write_reg (regs, dsc, 0, dsc->tmp[0], CANNOT_WRITE_PC);
if (dsc->u.ldst.xfersize > 4)
int immed = (op1 & 0x4) != 0;
int opcode;
ULONGEST rt_val, rt_val2 = 0, rn_val, rm_val = 0;
- CORE_ADDR from = dsc->insn_addr;
if (!insn_references_pc (insn, 0x000ff00ful))
return copy_unmodified (gdbarch, insn, "extra load/store", dsc);
internal_error (__FILE__, __LINE__,
_("copy_extra_ld_st: instruction decode error"));
- dsc->tmp[0] = displaced_read_reg (regs, from, 0);
- dsc->tmp[1] = displaced_read_reg (regs, from, 1);
- dsc->tmp[2] = displaced_read_reg (regs, from, 2);
+ dsc->tmp[0] = displaced_read_reg (regs, dsc, 0);
+ dsc->tmp[1] = displaced_read_reg (regs, dsc, 1);
+ dsc->tmp[2] = displaced_read_reg (regs, dsc, 2);
if (!immed)
- dsc->tmp[3] = displaced_read_reg (regs, from, 3);
+ dsc->tmp[3] = displaced_read_reg (regs, dsc, 3);
- rt_val = displaced_read_reg (regs, from, rt);
+ rt_val = displaced_read_reg (regs, dsc, rt);
if (bytesize[opcode] == 8)
- rt_val2 = displaced_read_reg (regs, from, rt + 1);
- rn_val = displaced_read_reg (regs, from, rn);
+ rt_val2 = displaced_read_reg (regs, dsc, rt + 1);
+ rn_val = displaced_read_reg (regs, dsc, rn);
if (!immed)
- rm_val = displaced_read_reg (regs, from, rm);
+ rm_val = displaced_read_reg (regs, dsc, rm);
displaced_write_reg (regs, dsc, 0, rt_val, CANNOT_WRITE_PC);
if (bytesize[opcode] == 8)
unsigned int rn = bits (insn, 16, 19);
unsigned int rm = bits (insn, 0, 3); /* Only valid if !immed. */
ULONGEST rt_val, rn_val, rm_val = 0;
- CORE_ADDR from = dsc->insn_addr;
if (!insn_references_pc (insn, 0x000ff00ful))
return copy_unmodified (gdbarch, insn, "load/store", dsc);
: (byte ? "strb" : "str"), usermode ? "t" : "",
(unsigned long) insn);
- dsc->tmp[0] = displaced_read_reg (regs, from, 0);
- dsc->tmp[2] = displaced_read_reg (regs, from, 2);
+ dsc->tmp[0] = displaced_read_reg (regs, dsc, 0);
+ dsc->tmp[2] = displaced_read_reg (regs, dsc, 2);
if (!immed)
- dsc->tmp[3] = displaced_read_reg (regs, from, 3);
+ dsc->tmp[3] = displaced_read_reg (regs, dsc, 3);
if (!load)
- dsc->tmp[4] = displaced_read_reg (regs, from, 4);
+ dsc->tmp[4] = displaced_read_reg (regs, dsc, 4);
- rt_val = displaced_read_reg (regs, from, rt);
- rn_val = displaced_read_reg (regs, from, rn);
+ rt_val = displaced_read_reg (regs, dsc, rt);
+ rn_val = displaced_read_reg (regs, dsc, rn);
if (!immed)
- rm_val = displaced_read_reg (regs, from, rm);
+ rm_val = displaced_read_reg (regs, dsc, rm);
displaced_write_reg (regs, dsc, 0, rt_val, CANNOT_WRITE_PC);
displaced_write_reg (regs, dsc, 2, rn_val, CANNOT_WRITE_PC);
cleanup_block_load_all (struct gdbarch *gdbarch, struct regcache *regs,
struct displaced_step_closure *dsc)
{
- ULONGEST from = dsc->insn_addr;
int inc = dsc->u.block.increment;
int bump_before = dsc->u.block.before ? (inc ? 4 : -4) : 0;
int bump_after = dsc->u.block.before ? 0 : (inc ? 4 : -4);
CORE_ADDR xfer_addr = dsc->u.block.xfer_addr;
int exception_return = dsc->u.block.load && dsc->u.block.user
&& (regmask & 0x8000) != 0;
- uint32_t status = displaced_read_reg (regs, from, ARM_PS_REGNUM);
+ uint32_t status = displaced_read_reg (regs, dsc, ARM_PS_REGNUM);
int do_transfer = condition_true (dsc->u.block.cond, status);
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
cleanup_block_store_pc (struct gdbarch *gdbarch, struct regcache *regs,
struct displaced_step_closure *dsc)
{
- ULONGEST from = dsc->insn_addr;
- uint32_t status = displaced_read_reg (regs, from, ARM_PS_REGNUM);
+ 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 stm_insn_addr;
struct regcache *regs,
struct displaced_step_closure *dsc)
{
- ULONGEST from = dsc->insn_addr;
- uint32_t status = displaced_read_reg (regs, from, ARM_PS_REGNUM);
+ uint32_t status = displaced_read_reg (regs, dsc, ARM_PS_REGNUM);
int load_executed = condition_true (dsc->u.block.cond, status), i;
unsigned int mask = dsc->u.block.regmask, write_reg = ARM_PC_REGNUM;
unsigned int regs_loaded = bitcount (mask);
if (read_reg != write_reg)
{
- ULONGEST rval = displaced_read_reg (regs, from, read_reg);
+ ULONGEST rval = displaced_read_reg (regs, dsc, read_reg);
displaced_write_reg (regs, dsc, write_reg, rval, LOAD_WRITE_PC);
if (debug_displaced)
fprintf_unfiltered (gdb_stdlog, _("displaced: LDM: move "
int before = bit (insn, 24);
int writeback = bit (insn, 21);
int rn = bits (insn, 16, 19);
- CORE_ADDR from = dsc->insn_addr;
/* Block transfers which don't mention PC can be run directly
out-of-line. */
fprintf_unfiltered (gdb_stdlog, "displaced: copying block transfer insn "
"%.8lx\n", (unsigned long) insn);
- dsc->u.block.xfer_addr = displaced_read_reg (regs, from, rn);
+ dsc->u.block.xfer_addr = displaced_read_reg (regs, dsc, rn);
dsc->u.block.rn = rn;
dsc->u.block.load = load;
unsigned int to = 0, from = 0, i, new_rn;
for (i = 0; i < num_in_list; i++)
- dsc->tmp[i] = displaced_read_reg (regs, from, i);
+ dsc->tmp[i] = displaced_read_reg (regs, dsc, i);
/* Writeback makes things complicated. We need to avoid clobbering
the base register with one of the registers in our modified
cleanup_svc (struct gdbarch *gdbarch, struct regcache *regs,
struct displaced_step_closure *dsc)
{
- CORE_ADDR from = dsc->insn_addr;
- CORE_ADDR resume_addr = from + 4;
+ CORE_ADDR resume_addr = dsc->insn_addr + 4;
if (debug_displaced)
fprintf_unfiltered (gdb_stdlog, "displaced: cleanup for svc, resume at "
copy_svc (struct gdbarch *gdbarch, uint32_t insn, CORE_ADDR to,
struct regcache *regs, struct displaced_step_closure *dsc)
{
- CORE_ADDR from = dsc->insn_addr;
-
/* Allow OS-specific code to override SVC handling. */
if (dsc->u.svc.copy_svc_os)
return dsc->u.svc.copy_svc_os (gdbarch, insn, to, regs, dsc);