#include "target_type.h"
#include "armv8_opcodes.h"
+#include "helper/time_support.h"
+
/**
* @file
/*----------------------------------------------------------------------*/
+static int dpmv8_write_dcc(struct armv8_common *armv8, uint32_t data)
+{
+ LOG_DEBUG("write DCC 0x%08" PRIx32, data);
+ return mem_ap_write_u32(armv8->debug_ap,
+ armv8->debug_base + CPUV8_DBG_DTRRX, data);
+}
+
+static int dpmv8_write_dcc_64(struct armv8_common *armv8, uint64_t data)
+{
+ int ret;
+ LOG_DEBUG("write DCC Low word 0x%08" PRIx32, (unsigned)data);
+ LOG_DEBUG("write DCC High word 0x%08" PRIx32, (unsigned)(data >> 32));
+ ret = mem_ap_write_u32(armv8->debug_ap,
+ armv8->debug_base + CPUV8_DBG_DTRRX, data);
+ ret += mem_ap_write_u32(armv8->debug_ap,
+ armv8->debug_base + CPUV8_DBG_DTRTX, data >> 32);
+ return ret;
+}
+
+static int dpmv8_read_dcc(struct armv8_common *armv8, uint32_t *data,
+ uint32_t *dscr_p)
+{
+ uint32_t dscr = DSCR_ITE;
+ int retval;
+
+ if (dscr_p)
+ dscr = *dscr_p;
+
+ /* Wait for DTRRXfull */
+ long long then = timeval_ms();
+ while ((dscr & DSCR_DTR_TX_FULL) == 0) {
+ retval = mem_ap_read_atomic_u32(armv8->debug_ap,
+ armv8->debug_base + CPUV8_DBG_DSCR,
+ &dscr);
+ if (retval != ERROR_OK)
+ return retval;
+ if (timeval_ms() > then + 1000) {
+ LOG_ERROR("Timeout waiting for read dcc");
+ return ERROR_FAIL;
+ }
+ }
+
+ retval = mem_ap_read_atomic_u32(armv8->debug_ap,
+ armv8->debug_base + CPUV8_DBG_DTRTX,
+ data);
+ if (retval != ERROR_OK)
+ return retval;
+ LOG_DEBUG("read DCC 0x%08" PRIx32, *data);
+
+ if (dscr_p)
+ *dscr_p = dscr;
+
+ return retval;
+}
+
+static int dpmv8_read_dcc_64(struct armv8_common *armv8, uint64_t *data,
+ uint32_t *dscr_p)
+{
+ uint32_t dscr = DSCR_ITE;
+ uint32_t higher;
+ int retval;
+
+ if (dscr_p)
+ dscr = *dscr_p;
+
+ /* Wait for DTRRXfull */
+ long long then = timeval_ms();
+ while ((dscr & DSCR_DTR_TX_FULL) == 0) {
+ retval = mem_ap_read_atomic_u32(armv8->debug_ap,
+ armv8->debug_base + CPUV8_DBG_DSCR,
+ &dscr);
+ if (retval != ERROR_OK)
+ return retval;
+ if (timeval_ms() > then + 1000) {
+ LOG_ERROR("Timeout waiting for read dcc");
+ return ERROR_FAIL;
+ }
+ }
+
+ retval = mem_ap_read_atomic_u32(armv8->debug_ap,
+ armv8->debug_base + CPUV8_DBG_DTRTX,
+ (uint32_t *)data);
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = mem_ap_read_atomic_u32(armv8->debug_ap,
+ armv8->debug_base + CPUV8_DBG_DTRRX,
+ &higher);
+ if (retval != ERROR_OK)
+ return retval;
+
+ *data = *(uint32_t *)data | (uint64_t)higher << 32;
+ LOG_DEBUG("read DCC 0x%16.16" PRIx64, *data);
+
+ if (dscr_p)
+ *dscr_p = dscr;
+
+ return retval;
+}
+
+static int dpmv8_dpm_prepare(struct arm_dpm *dpm)
+{
+ struct armv8_common *armv8 = dpm->arm->arch_info;
+ uint32_t dscr;
+ int retval;
+
+ /* set up invariant: INSTR_COMP is set after ever DPM operation */
+ long long then = timeval_ms();
+ for (;; ) {
+ retval = mem_ap_read_atomic_u32(armv8->debug_ap,
+ armv8->debug_base + CPUV8_DBG_DSCR,
+ &dscr);
+ if (retval != ERROR_OK)
+ return retval;
+ if ((dscr & DSCR_ITE) != 0)
+ break;
+ if (timeval_ms() > then + 1000) {
+ LOG_ERROR("Timeout waiting for dpm prepare");
+ return ERROR_FAIL;
+ }
+ }
+
+ /* this "should never happen" ... */
+ if (dscr & DSCR_DTR_RX_FULL) {
+ LOG_ERROR("DSCR_DTR_RX_FULL, dscr 0x%08" PRIx32, dscr);
+ /* Clear DCCRX */
+ retval = mem_ap_read_u32(armv8->debug_ap,
+ armv8->debug_base + CPUV8_DBG_DTRRX, &dscr);
+ if (retval != ERROR_OK)
+ return retval;
+
+ /* Clear sticky error */
+ retval = mem_ap_write_u32(armv8->debug_ap,
+ armv8->debug_base + CPUV8_DBG_DRCR, DRCR_CSE);
+ if (retval != ERROR_OK)
+ return retval;
+ }
+
+ return retval;
+}
+
+static int dpmv8_dpm_finish(struct arm_dpm *dpm)
+{
+ /* REVISIT what could be done here? */
+ return ERROR_OK;
+}
+
+static int dpmv8_exec_opcode(struct arm_dpm *dpm,
+ uint32_t opcode, uint32_t *p_dscr)
+{
+ struct armv8_common *armv8 = dpm->arm->arch_info;
+ uint32_t dscr = DSCR_ITE;
+ int retval;
+
+ LOG_DEBUG("exec opcode 0x%08" PRIx32, opcode);
+
+ if (p_dscr)
+ dscr = *p_dscr;
+
+ /* Wait for InstrCompl bit to be set */
+ long long then = timeval_ms();
+ while ((dscr & DSCR_ITE) == 0) {
+ retval = mem_ap_read_atomic_u32(armv8->debug_ap,
+ armv8->debug_base + CPUV8_DBG_DSCR, &dscr);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Could not read DSCR register, opcode = 0x%08" PRIx32, opcode);
+ return retval;
+ }
+ if (timeval_ms() > then + 1000) {
+ LOG_ERROR("Timeout waiting for aarch64_exec_opcode");
+ return ERROR_FAIL;
+ }
+ }
+
+ retval = mem_ap_write_u32(armv8->debug_ap,
+ armv8->debug_base + CPUV8_DBG_ITR, opcode);
+ if (retval != ERROR_OK)
+ return retval;
+
+ then = timeval_ms();
+ do {
+ retval = mem_ap_read_atomic_u32(armv8->debug_ap,
+ armv8->debug_base + CPUV8_DBG_DSCR, &dscr);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Could not read DSCR register");
+ return retval;
+ }
+ if (timeval_ms() > then + 1000) {
+ LOG_ERROR("Timeout waiting for aarch64_exec_opcode");
+ return ERROR_FAIL;
+ }
+ } while ((dscr & DSCR_ITE) == 0); /* Wait for InstrCompl bit to be set */
+
+ if (p_dscr)
+ *p_dscr = dscr;
+
+ return retval;
+}
+
+static int dpmv8_instr_execute(struct arm_dpm *dpm, uint32_t opcode)
+{
+ return dpmv8_exec_opcode(dpm, opcode, NULL);
+}
+
+static int dpmv8_instr_write_data_dcc(struct arm_dpm *dpm,
+ uint32_t opcode, uint32_t data)
+{
+ struct armv8_common *armv8 = dpm->arm->arch_info;
+ int retval;
+
+ retval = dpmv8_write_dcc(armv8, data);
+ if (retval != ERROR_OK)
+ return retval;
+
+ return dpmv8_exec_opcode(dpm, opcode, 0);
+}
+
+static int dpmv8_instr_write_data_dcc_64(struct arm_dpm *dpm,
+ uint32_t opcode, uint64_t data)
+{
+ struct armv8_common *armv8 = dpm->arm->arch_info;
+ int retval;
+
+ retval = dpmv8_write_dcc_64(armv8, data);
+ if (retval != ERROR_OK)
+ return retval;
+
+ return dpmv8_exec_opcode(dpm, opcode, 0);
+}
+
+static int dpmv8_instr_write_data_r0(struct arm_dpm *dpm,
+ uint32_t opcode, uint32_t data)
+{
+ struct armv8_common *armv8 = dpm->arm->arch_info;
+ uint32_t dscr = DSCR_ITE;
+ int retval;
+
+ retval = dpmv8_write_dcc(armv8, data);
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = dpmv8_exec_opcode(dpm, armv8_opcode(armv8, READ_REG_DTRRX), &dscr);
+ if (retval != ERROR_OK)
+ return retval;
+
+ /* then the opcode, taking data from R0 */
+ return dpmv8_exec_opcode(dpm, opcode, &dscr);
+}
+
+static int dpmv8_instr_write_data_r0_64(struct arm_dpm *dpm,
+ uint32_t opcode, uint64_t data)
+{
+ struct armv8_common *armv8 = dpm->arm->arch_info;
+ uint32_t dscr = DSCR_ITE;
+ int retval;
+
+ retval = dpmv8_write_dcc_64(armv8, data);
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = dpmv8_exec_opcode(dpm, ARMV8_MRS(SYSTEM_DBG_DBGDTR_EL0, 0), &dscr);
+ if (retval != ERROR_OK)
+ return retval;
+
+ /* then the opcode, taking data from R0 */
+ return dpmv8_exec_opcode(dpm, opcode, &dscr);
+}
+
+static int dpmv8_instr_cpsr_sync(struct arm_dpm *dpm)
+{
+ struct armv8_common *armv8 = dpm->arm->arch_info;
+ /* "Prefetch flush" after modifying execution status in CPSR */
+ return dpmv8_exec_opcode(dpm, armv8_opcode(armv8, ARMV8_OPC_DSB_SY), NULL);
+}
+
+static int dpmv8_instr_read_data_dcc(struct arm_dpm *dpm,
+ uint32_t opcode, uint32_t *data)
+{
+ struct armv8_common *armv8 = dpm->arm->arch_info;
+ uint32_t dscr = DSCR_ITE;
+ int retval;
+
+ /* the opcode, writing data to DCC */
+ retval = dpmv8_exec_opcode(dpm, opcode, &dscr);
+ if (retval != ERROR_OK)
+ return retval;
+
+ return dpmv8_read_dcc(armv8, data, &dscr);
+}
+
+static int dpmv8_instr_read_data_dcc_64(struct arm_dpm *dpm,
+ uint32_t opcode, uint64_t *data)
+{
+ struct armv8_common *armv8 = dpm->arm->arch_info;
+ uint32_t dscr = DSCR_ITE;
+ int retval;
+
+ /* the opcode, writing data to DCC */
+ retval = dpmv8_exec_opcode(dpm, opcode, &dscr);
+ if (retval != ERROR_OK)
+ return retval;
+
+ return dpmv8_read_dcc_64(armv8, data, &dscr);
+}
+
+static int dpmv8_instr_read_data_r0(struct arm_dpm *dpm,
+ uint32_t opcode, uint32_t *data)
+{
+ struct armv8_common *armv8 = dpm->arm->arch_info;
+ uint32_t dscr = DSCR_ITE;
+ int retval;
+
+ /* the opcode, writing data to R0 */
+ retval = dpmv8_exec_opcode(dpm, opcode, &dscr);
+ if (retval != ERROR_OK)
+ return retval;
+
+ /* write R0 to DCC */
+ retval = dpmv8_exec_opcode(dpm, armv8_opcode(armv8, WRITE_REG_DTRTX), &dscr);
+ if (retval != ERROR_OK)
+ return retval;
+
+ return dpmv8_read_dcc(armv8, data, &dscr);
+}
+
+static int dpmv8_instr_read_data_r0_64(struct arm_dpm *dpm,
+ uint32_t opcode, uint64_t *data)
+{
+ struct armv8_common *armv8 = dpm->arm->arch_info;
+ uint32_t dscr = DSCR_ITE;
+ int retval;
+
+ /* the opcode, writing data to R0 */
+ retval = dpmv8_exec_opcode(dpm, opcode, &dscr);
+ if (retval != ERROR_OK)
+ return retval;
+
+ /* write R0 to DCC */
+ retval = dpmv8_exec_opcode(dpm, ARMV8_MSR_GP(SYSTEM_DBG_DBGDTR_EL0, 0), &dscr);
+ if (retval != ERROR_OK)
+ return retval;
+
+ return dpmv8_read_dcc_64(armv8, data, &dscr);
+}
+
+#if 0
+static int dpmv8_bpwp_enable(struct arm_dpm *dpm, unsigned index_t,
+ target_addr_t addr, uint32_t control)
+{
+ struct armv8_common *armv8 = dpm->arm->arch_info;
+ uint32_t vr = armv8->debug_base;
+ uint32_t cr = armv8->debug_base;
+ int retval;
+
+ switch (index_t) {
+ case 0 ... 15: /* breakpoints */
+ vr += CPUV8_DBG_BVR_BASE;
+ cr += CPUV8_DBG_BCR_BASE;
+ break;
+ case 16 ... 31: /* watchpoints */
+ vr += CPUV8_DBG_WVR_BASE;
+ cr += CPUV8_DBG_WCR_BASE;
+ index_t -= 16;
+ break;
+ default:
+ return ERROR_FAIL;
+ }
+ vr += 16 * index_t;
+ cr += 16 * index_t;
+
+ LOG_DEBUG("A8: bpwp enable, vr %08x cr %08x",
+ (unsigned) vr, (unsigned) cr);
+
+ retval = mem_ap_write_atomic_u32(armv8->debug_ap, vr, addr);
+ if (retval != ERROR_OK)
+ return retval;
+ return mem_ap_write_atomic_u32(armv8->debug_ap, cr, control);
+}
+#endif
+
+static int dpmv8_bpwp_disable(struct arm_dpm *dpm, unsigned index_t)
+{
+ struct armv8_common *armv8 = dpm->arm->arch_info;
+ uint32_t cr;
+
+ switch (index_t) {
+ case 0 ... 15:
+ cr = armv8->debug_base + CPUV8_DBG_BCR_BASE;
+ break;
+ case 16 ... 31:
+ cr = armv8->debug_base + CPUV8_DBG_WCR_BASE;
+ index_t -= 16;
+ break;
+ default:
+ return ERROR_FAIL;
+ }
+ cr += 16 * index_t;
+
+ LOG_DEBUG("A: bpwp disable, cr %08x", (unsigned) cr);
+
+ /* clear control register */
+ return mem_ap_write_atomic_u32(armv8->debug_ap, cr, 0);
+}
+
/*
* Coprocessor support
*/
*/
int dpmv8_modeswitch(struct arm_dpm *dpm, enum arm_mode mode)
{
+ struct armv8_common *armv8 = (struct armv8_common *)dpm->arm->arch_info;
int retval;
uint32_t cpsr;
}
- retval = dpm->instr_write_data_r0(dpm, ARMV8_MSR_DSPSR(0), cpsr);
+ retval = dpm->instr_write_data_r0(dpm, armv8_opcode(armv8, WRITE_REG_DSPSR), cpsr);
if (retval != ERROR_OK)
return retval;
return retval;
}
+static int dpmv8_read_reg32(struct arm_dpm *dpm, struct reg *r, unsigned regnum)
+{
+ uint32_t value;
+ int retval = ERROR_FAIL;
+ bool valid = true;
+
+ switch (regnum) {
+ case 0 ... 14:
+ /* return via DCC: "MCR p14, 0, Rnum, c0, c5, 0" */
+ retval = dpm->instr_read_data_dcc(dpm,
+ T32_FMTITR(ARMV4_5_MCR(14, 0, regnum, 0, 5, 0)),
+ &value);
+ break;
+ case ARMV8_R31:
+ retval = dpm->instr_read_data_dcc(dpm,
+ T32_FMTITR(ARMV4_5_MCR(14, 0, 13, 0, 5, 0)),
+ &value);
+ break;
+ case ARMV8_PC:
+ retval = dpm->instr_read_data_r0(dpm,
+ T32_FMTITR(ARMV8_MRC_DLR(0)),
+ &value);
+ break;
+ case ARMV8_xPSR:
+ retval = dpm->instr_read_data_r0(dpm,
+ T32_FMTITR(ARMV8_MRC_DSPSR(0)),
+ &value);
+ break;
+ default:
+ LOG_DEBUG("READ: %s ignored", r->name);
+ retval = ERROR_OK;
+ value = 0xFFFFFFFF;
+ valid = false;
+ break;
+ }
+
+ if (retval == ERROR_OK) {
+ r->valid = valid;
+ r->dirty = false;
+ buf_set_u64(r->value, 0, 32, value);
+ LOG_DEBUG("READ: %s, %8.8x", r->name, (unsigned) value);
+ }
+ return retval;
+}
+
+static int dpmv8_write_reg32(struct arm_dpm *dpm, struct reg *r, unsigned regnum)
+{
+ int retval;
+ uint64_t value = buf_get_u64(r->value, 0, 32);
+
+ switch (regnum) {
+ case 0 ... 14:
+ /* load register from DCC: "MRC p14, 0, Rnum, c0, c5, 0" */
+ retval = dpm->instr_write_data_dcc(dpm,
+ T32_FMTITR(ARMV4_5_MRC(14, 0, regnum, 0, 5, 0)), value);
+ break;
+ case ARMV8_PC:/* PC
+ * read r0 from DCC; then "MOV pc, r0" */
+ retval = dpm->instr_write_data_r0(dpm,
+ T32_FMTITR(ARMV8_MCR_DLR(0)), value);
+ break;
+ case ARMV8_xPSR: /* CPSR */
+ /* read r0 from DCC, then "MCR r0, DSPSR" */
+ retval = dpm->instr_write_data_r0(dpm,
+ T32_FMTITR(ARMV8_MCR_DSPSR(0)), value);
+ break;
+ default:
+ retval = ERROR_OK;
+ LOG_DEBUG("WRITE: %s ignored", r->name);
+ break;
+ }
+
+ if (retval == ERROR_OK) {
+ r->dirty = false;
+ LOG_DEBUG("WRITE: %s, %8.8x", r->name, (unsigned) value);
+ }
+
+ return retval;
+}
+
/* just read the register -- rely on the core mode being right */
static int dpmv8_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum)
{
ARMV8_MSR_GP(SYSTEM_DBG_DBGDTR_EL0, regnum),
&value_64);
break;
- case 31:
+ case ARMV8_R31:
retval = dpm->instr_read_data_r0_64(dpm,
ARMV8_MOVFSP_64(0),
&value_64);
break;
- case 32:
+ case ARMV8_PC:
retval = dpm->instr_read_data_r0_64(dpm,
ARMV8_MRS_DLR(0),
&value_64);
break;
- case 33:
+ case ARMV8_xPSR:
retval = dpm->instr_read_data_r0(dpm,
ARMV8_MRS_DSPSR(0),
&value);
+ break;
default:
LOG_DEBUG("READ: %s fail", r->name);
break;
if (retval == ERROR_OK) {
r->valid = true;
r->dirty = false;
- buf_set_u64(r->value, 0, 32, value_64);
- if (r->size == 64)
+ if (r->size == 64) {
+ buf_set_u64(r->value, 0, 64, value_64);
LOG_DEBUG("READ: %s, %16.8llx", r->name, (unsigned long long) value_64);
- else
+ } else {
+ buf_set_u32(r->value, 0, 32, value);
LOG_DEBUG("READ: %s, %8.8x", r->name, (unsigned) value);
+ }
}
return retval;
}
ARMV8_MRS(SYSTEM_DBG_DBGDTR_EL0, regnum),
value_64);
break;
- case 31:
+ case ARMV8_R31:
value_64 = buf_get_u64(r->value, 0, 64);
retval = dpm->instr_write_data_r0_64(dpm,
ARMV8_MOVTSP_64(0),
value_64);
break;
- case 32:
+ case ARMV8_PC:
value_64 = buf_get_u64(r->value, 0, 64);
retval = dpm->instr_write_data_r0_64(dpm,
ARMV8_MSR_DLR(0),
value_64);
break;
- case 33:
+ case ARMV8_xPSR:
value = buf_get_u32(r->value, 0, 32);
retval = dpm->instr_write_data_r0(dpm,
ARMV8_MSR_DSPSR(0),
value);
+ break;
default:
LOG_DEBUG("write: %s fail", r->name);
break;
return retval;
}
+static inline enum arm_state dpm_get_core_state(uint32_t dscr)
+{
+ int el = (dscr >> 8) & 0x3;
+ int rw = (dscr >> 10) & 0xF;
+
+ LOG_DEBUG("EL:%i, RW:0x%x", el, rw);
+
+ /* DSCR.RW = 0b1111 - all EL are using AArch64 state */
+ if (rw == 0xF)
+ return ARM_STATE_AARCH64;
+
+ /* DSCR.RW = 0b1110 - all EL > 0 are using AArch64 state */
+ if (rw == 0xE && el > 0)
+ return ARM_STATE_AARCH64;
+
+ /* DSCR.RW = 0b110x - all EL > 1 are using Aarch64 state */
+ if ((rw & 0xE) == 0xC && el > 1)
+ return ARM_STATE_AARCH64;
+
+ /* DSCR.RW = 0b10xx - all EL > 2 are using Aarch64 state */
+ if ((rw & 0xC) == 0x8 && el > 2)
+ return ARM_STATE_AARCH64;
+
+ /* DSCR.RW = 0b0xxx - all EL are using AArch32 state */
+ if ((rw & 0x8) == 0)
+ return ARM_STATE_ARM;
+
+ return ARM_STATE_ARM;
+}
+
/**
* Read basic registers of the the current context: R0 to R15, and CPSR;
* sets the core mode (such as USR or IRQ) and state (such as ARM or Thumb).
int armv8_dpm_read_current_registers(struct arm_dpm *dpm)
{
struct arm *arm = dpm->arm;
+ struct armv8_common *armv8 = (struct armv8_common *)arm->arch_info;
+ enum arm_state core_state;
uint32_t cpsr;
+
int retval;
struct reg *r;
if (retval != ERROR_OK)
return retval;
+ core_state = dpm_get_core_state(dpm->dscr);
+
+ armv8_select_opcodes(armv8, core_state);
+
/* read R0 first (it's used for scratch), then CPSR */
r = arm->core_cache->reg_list + 0;
if (!r->valid) {
- retval = dpmv8_read_reg(dpm, r, 0);
+ retval = core_state == ARM_STATE_AARCH64 ?
+ dpmv8_read_reg(dpm, r, 0) : dpmv8_read_reg32(dpm, r, 0);
if (retval != ERROR_OK)
goto fail;
}
r->dirty = true;
+
/* read cpsr to r0 and get it back */
- retval = dpm->instr_read_data_r0(dpm, ARMV8_MRS_DSPSR(0), &cpsr);
+ retval = dpm->instr_read_data_r0(dpm, armv8_opcode(armv8, READ_REG_DSPSR), &cpsr);
if (retval != ERROR_OK)
goto fail;
if (r->valid)
continue;
- retval = dpmv8_read_reg(dpm, r, i);
+ retval = core_state == ARM_STATE_AARCH64 ?
+ dpmv8_read_reg(dpm, r, i) : dpmv8_read_reg32(dpm, r, i);
+
if (retval != ERROR_OK)
goto fail;
}
struct arm *arm = dpm->arm;
struct reg_cache *cache = arm->core_cache;
int retval;
+ bool is_aarch64 = arm->core_state == ARM_STATE_AARCH64;
retval = dpm->prepare(dpm);
if (retval != ERROR_OK)
r = cache->reg_list[i].arch_info;
regnum = r->num;
- retval = dpmv8_write_reg(dpm,
- &cache->reg_list[i],
- regnum);
+ retval = is_aarch64 ? dpmv8_write_reg(dpm, &cache->reg_list[i], regnum)
+ : dpmv8_write_reg32(dpm, &cache->reg_list[i], regnum);
if (retval != ERROR_OK)
goto done;
}
goto done;
arm->cpsr->dirty = false;
- retval = dpmv8_write_reg(dpm, arm->pc, (arm->core_cache->num_regs - 2));
+ retval = is_aarch64 ? dpmv8_write_reg(dpm, arm->pc, (arm->core_cache->num_regs - 2))
+ : dpmv8_write_reg32(dpm, arm->pc, (arm->core_cache->num_regs - 2));
if (retval != ERROR_OK)
goto done;
arm->pc->dirty = false;
/* flush R0 -- it's *very* dirty by now */
- retval = dpmv8_write_reg(dpm, &cache->reg_list[0], 0);
+ retval = is_aarch64 ? dpmv8_write_reg(dpm, &cache->reg_list[0], 0)
+ : dpmv8_write_reg32(dpm, &cache->reg_list[0], 0);
if (retval != ERROR_OK)
goto done;
cache->reg_list[0].dirty = false;
if (retval != ERROR_OK)
return retval;
- retval = dpmv8_read_reg(dpm, r, regnum);
+ retval = arm->core_state == ARM_STATE_AARCH64 ?
+ dpmv8_read_reg(dpm, r, regnum) : dpmv8_read_reg32(dpm, r, regnum);
if (retval != ERROR_OK)
goto fail;
if (retval != ERROR_OK)
return retval;
- retval = dpmv8_write_reg(dpm, r, regnum);
+ retval = arm->core_state == ARM_STATE_AARCH64 ?
+ dpmv8_write_reg(dpm, r, regnum) : dpmv8_write_reg32(dpm, r, regnum);
+
/* always clean up, regardless of error */
/* (void) */ dpm->finish(dpm);
/* Examine debug reason */
switch (DSCR_ENTRY(dscr)) {
/* FALL THROUGH -- assume a v6 core in abort mode */
- case DSCRV8_ENTRY_HLT: /* HALT request from debugger */
case DSCRV8_ENTRY_EXT_DEBUG: /* EDBGRQ */
target->debug_reason = DBG_REASON_DBGRQ;
break;
case DSCRV8_ENTRY_HALT_STEP_EXECLU: /* HALT step */
- case DSCRV8_ENTRY_BKPT: /* SW BKPT */
+ case DSCRV8_ENTRY_HALT_STEP_NORMAL: /* Halt step*/
+ case DSCRV8_ENTRY_HALT_STEP:
+ target->debug_reason = DBG_REASON_SINGLESTEP;
+ break;
+ case DSCRV8_ENTRY_HLT: /* HLT instruction (software breakpoint) */
+ case DSCRV8_ENTRY_BKPT: /* SW BKPT (?) */
case DSCRV8_ENTRY_RESET_CATCH: /* Reset catch */
case DSCRV8_ENTRY_OS_UNLOCK: /*OS unlock catch*/
case DSCRV8_ENTRY_EXCEPTION_CATCH: /*exception catch*/
- case DSCRV8_ENTRY_HALT_STEP_NORMAL: /* Halt step*/
case DSCRV8_ENTRY_SW_ACCESS_DBG: /*SW access dbg register*/
target->debug_reason = DBG_REASON_BREAKPOINT;
break;
arm->mcr = dpmv8_mcr;
arm->mrs = dpmv8_mrs;
arm->msr = dpmv8_msr;
+
+ dpm->prepare = dpmv8_dpm_prepare;
+ dpm->finish = dpmv8_dpm_finish;
+
+ dpm->instr_execute = dpmv8_instr_execute;
+ dpm->instr_write_data_dcc = dpmv8_instr_write_data_dcc;
+ dpm->instr_write_data_dcc_64 = dpmv8_instr_write_data_dcc_64;
+ dpm->instr_write_data_r0 = dpmv8_instr_write_data_r0;
+ dpm->instr_write_data_r0_64 = dpmv8_instr_write_data_r0_64;
+ dpm->instr_cpsr_sync = dpmv8_instr_cpsr_sync;
+
+ dpm->instr_read_data_dcc = dpmv8_instr_read_data_dcc;
+ dpm->instr_read_data_dcc_64 = dpmv8_instr_read_data_dcc_64;
+ dpm->instr_read_data_r0 = dpmv8_instr_read_data_r0;
+ dpm->instr_read_data_r0_64 = dpmv8_instr_read_data_r0_64;
+
+ dpm->arm_reg_current = armv8_reg_current;
+
+/* dpm->bpwp_enable = dpmv8_bpwp_enable; */
+ dpm->bpwp_disable = dpmv8_bpwp_disable;
+
/* breakpoint setup -- optional until it works everywhere */
if (!target->type->add_breakpoint) {
target->type->add_breakpoint = dpmv8_add_breakpoint;