-/* SPDX-License-Identifier: GPL-2.0-or-later */
+// SPDX-License-Identifier: GPL-2.0-or-later
/***************************************************************************
* Generic Xtensa target API for OpenOCD *
#define XT_REG_A3 (xtensa_regs[XT_REG_IDX_AR3].reg_num)
#define XT_REG_A4 (xtensa_regs[XT_REG_IDX_AR4].reg_num)
-#define XT_PS_REG_NUM_BASE (0xc0U) /* (EPS2 - 2), for adding DBGLEVEL */
-#define XT_PC_REG_NUM_BASE (0xb0U) /* (EPC1 - 1), for adding DBGLEVEL */
+#define XT_PS_REG_NUM (0xe6U)
+#define XT_EPS_REG_NUM_BASE (0xc0U) /* (EPS2 - 2), for adding DBGLEVEL */
+#define XT_EPC_REG_NUM_BASE (0xb0U) /* (EPC1 - 1), for adding DBGLEVEL */
#define XT_PC_REG_NUM_VIRTUAL (0xffU) /* Marker for computing PC (EPC[DBGLEVEL) */
#define XT_PC_DBREG_NUM_BASE (0x20U) /* External (i.e., GDB) access */
XT_MK_REG_DESC("ar63", 0x3F, XT_REG_GENERAL, 0),
XT_MK_REG_DESC("windowbase", 0x48, XT_REG_SPECIAL, 0),
XT_MK_REG_DESC("windowstart", 0x49, XT_REG_SPECIAL, 0),
- XT_MK_REG_DESC("ps", 0xE6, XT_REG_SPECIAL, 0), /* PS (not mapped through EPS[]) */
+ XT_MK_REG_DESC("ps", XT_PS_REG_NUM, XT_REG_SPECIAL, 0), /* PS (not mapped through EPS[]) */
XT_MK_REG_DESC("ibreakenable", 0x60, XT_REG_SPECIAL, 0),
XT_MK_REG_DESC("ddr", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD),
XT_MK_REG_DESC("ibreaka0", 0x80, XT_REG_SPECIAL, 0),
static void xtensa_queue_exec_ins_wide(struct xtensa *xtensa, uint8_t *ops, uint8_t oplen)
{
- if ((oplen > 0) && (oplen <= 64)) {
- uint32_t opsw[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; /* 8 DIRx regs: max width 64B */
- uint8_t oplenw = (oplen + 3) / 4;
- if (xtensa->target->endianness == TARGET_BIG_ENDIAN)
- buf_bswap32((uint8_t *)opsw, ops, oplenw * 4);
- else
- memcpy(opsw, ops, oplen);
+ const int max_oplen = 64; /* 8 DIRx regs: max width 64B */
+ if ((oplen > 0) && (oplen <= max_oplen)) {
+ uint8_t ops_padded[max_oplen];
+ memcpy(ops_padded, ops, oplen);
+ memset(ops_padded + oplen, 0, max_oplen - oplen);
+ unsigned int oplenw = DIV_ROUND_UP(oplen, sizeof(uint32_t));
for (int32_t i = oplenw - 1; i > 0; i--)
- xtensa_queue_dbg_reg_write(xtensa, XDMREG_DIR0 + i, opsw[i]);
+ xtensa_queue_dbg_reg_write(xtensa,
+ XDMREG_DIR0 + i,
+ target_buffer_get_u32(xtensa->target, &ops_padded[sizeof(uint32_t)*i]));
/* Write DIR0EXEC last */
- xtensa_queue_dbg_reg_write(xtensa, XDMREG_DIR0EXEC, opsw[0]);
+ xtensa_queue_dbg_reg_write(xtensa,
+ XDMREG_DIR0EXEC,
+ target_buffer_get_u32(xtensa->target, &ops_padded[0]));
}
}
/* reg number of PC for debug interrupt depends on NDEBUGLEVEL
**/
reg_num =
- (XT_PC_REG_NUM_BASE +
+ (XT_EPC_REG_NUM_BASE +
xtensa->core_config->debug.irq_level);
xtensa_queue_exec_ins(xtensa, XT_INS_WSR(xtensa, reg_num, XT_REG_A3));
}
return ERROR_TARGET_FAILURE;
}
LOG_DEBUG("OCD_ID = %08" PRIx32, xtensa->dbg_mod.device_id);
- if (!target_was_examined(target))
- target_set_examined(target);
+ target_set_examined(target);
xtensa_smpbreak_write(xtensa, xtensa->smp_break);
return ERROR_OK;
}
struct xtensa *xtensa = target_to_xtensa(target);
LOG_TARGET_DEBUG(target, "target_number=%i, begin", target->target_number);
- target->state = TARGET_RESET;
xtensa_queue_pwr_reg_write(xtensa,
XDMREG_PWRCTL,
PWRCTL_JTAGDEBUGUSE(xtensa) | PWRCTL_DEBUGWAKEUP(xtensa) | PWRCTL_MEMWAKEUP(xtensa) |
int res = xtensa_dm_queue_execute(&xtensa->dbg_mod);
if (res != ERROR_OK)
return res;
+
+ /* registers are now invalid */
xtensa->reset_asserted = true;
- return res;
+ register_cache_invalidate(xtensa->core_cache);
+ target->state = TARGET_RESET;
+ return ERROR_OK;
}
int xtensa_deassert_reset(struct target *target)
case XT_REG_SPECIAL:
if (reg_num == XT_PC_REG_NUM_VIRTUAL) {
/* reg number of PC for debug interrupt depends on NDEBUGLEVEL */
- reg_num = (XT_PC_REG_NUM_BASE + xtensa->core_config->debug.irq_level);
+ reg_num = XT_EPC_REG_NUM_BASE + xtensa->core_config->debug.irq_level;
+ } else if (reg_num == xtensa_regs[XT_REG_IDX_PS].reg_num) {
+ /* reg number of PS for debug interrupt depends on NDEBUGLEVEL */
+ reg_num = XT_EPS_REG_NUM_BASE + xtensa->core_config->debug.irq_level;
} else if (reg_num == xtensa_regs[XT_REG_IDX_CPENABLE].reg_num) {
/* CPENABLE already read/updated; don't re-read */
reg_fetched = false;
target->debug_reason = DBG_REASON_SINGLESTEP;
target->state = TARGET_HALTED;
- target_call_event_callbacks(target, TARGET_EVENT_HALTED);
LOG_DEBUG("Done stepping, PC=%" PRIX32, cur_pc);
if (cause & DEBUGCAUSE_DB) {
int xtensa_step(struct target *target, int current, target_addr_t address, int handle_breakpoints)
{
- return xtensa_do_step(target, current, address, handle_breakpoints);
+ int retval = xtensa_do_step(target, current, address, handle_breakpoints);
+ if (retval != ERROR_OK)
+ return retval;
+ target_call_event_callbacks(target, TARGET_EVENT_HALTED);
+
+ return ERROR_OK;
}
/**
}
}
- if (addrstart_al == address && addrend_al == address + (size * count)) {
- albuff = buffer;
- } else {
- albuff = malloc(addrend_al - addrstart_al);
- if (!albuff) {
- LOG_TARGET_ERROR(target, "Out of memory allocating %" TARGET_PRIdADDR " bytes!",
- addrend_al - addrstart_al);
- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
- }
+ unsigned int alloc_bytes = ALIGN_UP(addrend_al - addrstart_al, sizeof(uint32_t));
+ albuff = calloc(alloc_bytes, 1);
+ if (!albuff) {
+ LOG_TARGET_ERROR(target, "Out of memory allocating %" PRId64 " bytes!",
+ addrend_al - addrstart_al);
+ return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
/* We're going to use A3 here */
if (res != ERROR_OK) {
if (xtensa->probe_lsddr32p != 0) {
/* Disable fast memory access instructions and retry before reporting an error */
- LOG_TARGET_INFO(target, "Disabling LDDR32.P/SDDR32.P");
+ LOG_TARGET_DEBUG(target, "Disabling LDDR32.P/SDDR32.P");
xtensa->probe_lsddr32p = 0;
- res = xtensa_read_memory(target, address, size, count, buffer);
+ res = xtensa_read_memory(target, address, size, count, albuff);
bswap = false;
} else {
LOG_TARGET_WARNING(target, "Failed reading %d bytes at address "TARGET_ADDR_FMT,
if (bswap)
buf_bswap32(albuff, albuff, addrend_al - addrstart_al);
- if (albuff != buffer) {
- memcpy(buffer, albuff + (address & 3), (size * count));
- free(albuff);
- }
-
+ memcpy(buffer, albuff + (address & 3), (size * count));
+ free(albuff);
return res;
}
albuff = malloc(addrend_al - addrstart_al);
}
if (!albuff) {
- LOG_TARGET_ERROR(target, "Out of memory allocating %" TARGET_PRIdADDR " bytes!",
+ LOG_TARGET_ERROR(target, "Out of memory allocating %" PRId64 " bytes!",
addrend_al - addrstart_al);
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
unsigned int j;
for (j = 0; j < reg_cache->num_regs; j++) {
if (!strcmp(reg_cache->reg_list[j].name, xtensa->contiguous_regs_desc[i]->name)) {
+ /* Register number field is not filled above.
+ Here we are assigning the corresponding index from the contiguous reg list.
+ These indexes are in the same order with gdb g-packet request/response.
+ Some more changes may be required for sparse reg lists.
+ */
+ reg_cache->reg_list[j].number = i;
xtensa->contiguous_regs_list[i] = &(reg_cache->reg_list[j]);
LOG_TARGET_DEBUG(target,
"POPULATE contiguous regs list: %-16s, dbreg_num 0x%04x",
else
rptr->flags = 0;
- if ((rptr->reg_num == (XT_PS_REG_NUM_BASE + xtensa->core_config->debug.irq_level)) &&
- (xtensa->core_config->core_type == XT_LX) && (rptr->type == XT_REG_SPECIAL)) {
+ if (rptr->reg_num == (XT_EPS_REG_NUM_BASE + xtensa->core_config->debug.irq_level) &&
+ xtensa->core_config->core_type == XT_LX && rptr->type == XT_REG_SPECIAL) {
xtensa->eps_dbglevel_idx = XT_NUM_REGS + xtensa->num_optregs - 1;
LOG_DEBUG("Setting PS (%s) index to %d", rptr->name, xtensa->eps_dbglevel_idx);
}