static int xscale_resume(struct target *, int current,
uint32_t address, int handle_breakpoints, int debug_execution);
static int xscale_debug_entry(struct target *);
-static int xscale_restore_context(struct target *);
+static int xscale_restore_banked(struct target *);
static int xscale_get_reg(struct reg *reg);
static int xscale_set_reg(struct reg *reg, uint8_t *buf);
static int xscale_set_breakpoint(struct target *, struct breakpoint *);
uint8_t field2_check_mask = 0x1;
jtag_set_end_state(TAP_DRPAUSE);
- xscale_jtag_set_instr(target->tap, XSCALE_SELDCSR);
+ xscale_jtag_set_instr(target->tap,
+ XSCALE_SELDCSR << xscale->xscale_variant);
buf_set_u32(&field0, 1, 1, xscale->hold_rst);
buf_set_u32(&field0, 2, 1, xscale->external_debug_break);
if (num_words == 0)
return ERROR_INVALID_ARGUMENTS;
+ struct xscale_common *xscale = target_to_xscale(target);
int retval = ERROR_OK;
tap_state_t path[3];
struct scan_field fields[3];
fields[2].check_mask = &field2_check_mask;
jtag_set_end_state(TAP_IDLE);
- xscale_jtag_set_instr(target->tap, XSCALE_DBGTX);
+ xscale_jtag_set_instr(target->tap,
+ XSCALE_DBGTX << xscale->xscale_variant);
jtag_add_runtest(1, jtag_get_end_state()); /* ensures that we're in the TAP_IDLE state as the above could be a no-op */
/* repeat until all words have been collected */
jtag_set_end_state(TAP_IDLE);
- xscale_jtag_set_instr(target->tap, XSCALE_DBGTX);
+ xscale_jtag_set_instr(target->tap,
+ XSCALE_DBGTX << xscale->xscale_variant);
path[0] = TAP_DRSELECT;
path[1] = TAP_DRCAPTURE;
jtag_set_end_state(TAP_IDLE);
- xscale_jtag_set_instr(target->tap, XSCALE_DBGRX);
+ xscale_jtag_set_instr(target->tap,
+ XSCALE_DBGRX << xscale->xscale_variant);
memset(&fields, 0, sizeof fields);
/* send count elements of size byte to the debug handler */
static int xscale_send(struct target *target, uint8_t *buffer, int count, int size)
{
+ struct xscale_common *xscale = target_to_xscale(target);
uint32_t t[3];
int bits[3];
int retval;
jtag_set_end_state(TAP_IDLE);
- xscale_jtag_set_instr(target->tap, XSCALE_DBGRX);
+ xscale_jtag_set_instr(target->tap,
+ XSCALE_DBGRX << xscale->xscale_variant);
bits[0]=3;
t[0]=0;
xscale->external_debug_break = ext_dbg_brk;
jtag_set_end_state(TAP_IDLE);
- xscale_jtag_set_instr(target->tap, XSCALE_SELDCSR);
+ xscale_jtag_set_instr(target->tap,
+ XSCALE_SELDCSR << xscale->xscale_variant);
buf_set_u32(&field0, 1, 1, xscale->hold_rst);
buf_set_u32(&field0, 2, 1, xscale->external_debug_break);
static int xscale_load_ic(struct target *target, uint32_t va, uint32_t buffer[8])
{
+ struct xscale_common *xscale = target_to_xscale(target);
uint8_t packet[4];
uint8_t cmd;
int word;
/* LDIC into IR */
jtag_set_end_state(TAP_IDLE);
- xscale_jtag_set_instr(target->tap, XSCALE_LDIC);
+ xscale_jtag_set_instr(target->tap,
+ XSCALE_LDIC << xscale->xscale_variant);
/* CMD is b011 to load a cacheline into the Mini ICache.
* Loading into the main ICache is deprecated, and unused.
static int xscale_invalidate_ic_line(struct target *target, uint32_t va)
{
+ struct xscale_common *xscale = target_to_xscale(target);
uint8_t packet[4];
uint8_t cmd;
struct scan_field fields[2];
jtag_set_end_state(TAP_IDLE);
- xscale_jtag_set_instr(target->tap, XSCALE_LDIC);
+ xscale_jtag_set_instr(target->tap,
+ XSCALE_LDIC << xscale->xscale_variant);
/* CMD for invalidate IC line b000, bits [6:4] b000 */
buf_set_u32(&cmd, 0, 6, 0x0);
arm_mode_name(armv4_5->core_mode));
/* get banked registers, r8 to r14, and spsr if not in USR/SYS mode */
- if ((armv4_5->core_mode != ARMV4_5_MODE_USR) && (armv4_5->core_mode != ARMV4_5_MODE_SYS))
- {
+ if (armv4_5->spsr) {
xscale_receive(target, buffer, 8);
- buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 16).value, 0, 32, buffer[7]);
- ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 16).dirty = 0;
- ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 16).valid = 1;
+ buf_set_u32(armv4_5->spsr->value, 0, 32, buffer[7]);
+ armv4_5->spsr->dirty = false;
+ armv4_5->spsr->valid = true;
}
else
{
xscale_receive(target, buffer, 7);
}
- /* move data from buffer to register cache */
+ /* move data from buffer to right banked register in cache */
for (i = 8; i <= 14; i++)
{
- buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i).value, 0, 32, buffer[i - 8]);
- ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i).dirty = 0;
- ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i).valid = 1;
+ struct reg *r = arm_reg_current(armv4_5, i);
+
+ buf_set_u32(r->value, 0, 32, buffer[i - 8]);
+ r->dirty = false;
+ r->valid = true;
}
/* examine debug reason */
xscale_enable_single_step(target, next_pc);
/* restore banked registers */
- xscale_restore_context(target);
+ retval = xscale_restore_banked(target);
/* send resume request (command 0x30 or 0x31)
* clean the trace buffer if it is to be enabled (0x62) */
xscale_enable_watchpoints(target);
/* restore banked registers */
- xscale_restore_context(target);
+ retval = xscale_restore_banked(target);
/* send resume request (command 0x30 or 0x31)
* clean the trace buffer if it is to be enabled (0x62) */
return retval;
/* restore banked registers */
- if ((retval = xscale_restore_context(target)) != ERROR_OK)
+ if ((retval = xscale_restore_banked(target)) != ERROR_OK)
return retval;
/* send resume request (command 0x30 or 0x31)
* end up in T-L-R, which would reset JTAG
*/
jtag_set_end_state(TAP_IDLE);
- xscale_jtag_set_instr(target->tap, XSCALE_SELDCSR);
+ xscale_jtag_set_instr(target->tap,
+ XSCALE_SELDCSR << xscale->xscale_variant);
/* set Hold reset, Halt mode and Trap Reset */
buf_set_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 30, 1, 0x1);
*/
for (i = 1; i < 7; i++)
{
- int valid = 1;
+ enum armv4_5_mode mode = armv4_5_number_to_mode(i);
+ bool valid = true;
+ struct reg *r;
+
+ if (mode == ARMV4_5_MODE_USR)
+ continue;
/* check if there are invalid registers in the current mode
*/
- for (j = 0; j <= 16; j++)
+ for (j = 0; valid && j <= 16; j++)
{
- if (ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), j).valid == 0)
- valid = 0;
+ if (!ARMV4_5_CORE_REG_MODE(armv4_5->core_cache,
+ mode, j).valid)
+ valid = false;
}
+ if (valid)
+ continue;
- if (!valid)
- {
- uint32_t tmp_cpsr;
-
- /* request banked registers */
- xscale_send_u32(target, 0x0);
+ /* request banked registers */
+ xscale_send_u32(target, 0x0);
- tmp_cpsr = 0x0;
- tmp_cpsr |= armv4_5_number_to_mode(i);
- tmp_cpsr |= 0xc0; /* I/F bits */
+ /* send CPSR for desired bank mode */
+ xscale_send_u32(target, mode | 0xc0 /* I/F bits */);
- /* send CPSR for desired mode */
- xscale_send_u32(target, tmp_cpsr);
+ /* get banked registers: r8 to r14; and SPSR
+ * except in USR/SYS mode
+ */
+ if (mode != ARMV4_5_MODE_SYS) {
+ /* SPSR */
+ r = &ARMV4_5_CORE_REG_MODE(armv4_5->core_cache,
+ mode, 16);
+
+ xscale_receive(target, buffer, 8);
+
+ buf_set_u32(r->value, 0, 32, buffer[7]);
+ r->dirty = false;
+ r->valid = true;
+ } else {
+ xscale_receive(target, buffer, 7);
+ }
- /* get banked registers, r8 to r14, and spsr if not in USR/SYS mode */
- if ((armv4_5_number_to_mode(i) != ARMV4_5_MODE_USR) && (armv4_5_number_to_mode(i) != ARMV4_5_MODE_SYS))
- {
- xscale_receive(target, buffer, 8);
- buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 16).value, 0, 32, buffer[7]);
- ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), 16).dirty = 0;
- ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), 16).valid = 1;
- }
- else
- {
- xscale_receive(target, buffer, 7);
- }
+ /* move data from buffer to register cache */
+ for (j = 8; j <= 14; j++)
+ {
+ r = &ARMV4_5_CORE_REG_MODE(armv4_5->core_cache,
+ mode, j);
- /* move data from buffer to register cache */
- for (j = 8; j <= 14; j++)
- {
- buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), j).value, 0, 32, buffer[j - 8]);
- ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), j).dirty = 0;
- ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), j).valid = 1;
- }
+ buf_set_u32(r->value, 0, 32, buffer[j - 8]);
+ r->dirty = false;
+ r->valid = true;
}
}
return ERROR_OK;
}
-static int xscale_restore_context(struct target *target)
+static int xscale_restore_banked(struct target *target)
{
struct arm *armv4_5 = target_to_armv4_5(target);
}
/* iterate through processor modes (FIQ, IRQ, SVC, ABT, UND and SYS)
- * we can't enter User mode on an XScale (unpredictable),
- * but User shares registers with SYS
- */
+ * and check if any banked registers need to be written. Ignore
+ * USR mode (number 0) in favor of SYS; we can't enter User mode on
+ * an XScale (unpredictable), but they share all registers.
+ */
for (i = 1; i < 7; i++)
{
- int dirty = 0;
+ enum armv4_5_mode mode = armv4_5_number_to_mode(i);
+ struct reg *r;
- /* check if there are invalid registers in the current mode
- */
+ if (mode == ARMV4_5_MODE_USR)
+ continue;
+
+ /* check if there are dirty registers in this mode */
for (j = 8; j <= 14; j++)
{
- if (ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), j).dirty == 1)
- dirty = 1;
+ if (ARMV4_5_CORE_REG_MODE(armv4_5->core_cache,
+ mode, j).dirty)
+ goto dirty;
}
/* if not USR/SYS, check if the SPSR needs to be written */
- if ((armv4_5_number_to_mode(i) != ARMV4_5_MODE_USR) && (armv4_5_number_to_mode(i) != ARMV4_5_MODE_SYS))
+ if (mode != ARMV4_5_MODE_SYS)
{
- if (ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), 16).dirty == 1)
- dirty = 1;
+ if (ARMV4_5_CORE_REG_MODE(armv4_5->core_cache,
+ mode, 16).dirty)
+ goto dirty;
}
- if (dirty)
- {
- uint32_t tmp_cpsr;
-
- /* send banked registers */
- xscale_send_u32(target, 0x1);
+ /* there's nothing to flush for this mode */
+ continue;
- tmp_cpsr = 0x0;
- tmp_cpsr |= armv4_5_number_to_mode(i);
- tmp_cpsr |= 0xc0; /* I/F bits */
+dirty:
+ /* command 0x1: "send banked registers" */
+ xscale_send_u32(target, 0x1);
- /* send CPSR for desired mode */
- xscale_send_u32(target, tmp_cpsr);
+ /* send CPSR for desired mode */
+ xscale_send_u32(target, mode | 0xc0 /* I/F bits */);
- /* send banked registers, r8 to r14, and spsr if not in USR/SYS mode */
- for (j = 8; j <= 14; j++)
- {
- xscale_send_u32(target, buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, j).value, 0, 32));
- ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), j).dirty = 0;
- }
+ /* send r8 to r14/lr ... only FIQ needs more than r13..r14,
+ * but this protocol doesn't understand that nuance.
+ */
+ for (j = 8; j <= 14; j++) {
+ r = &ARMV4_5_CORE_REG_MODE(armv4_5->core_cache,
+ mode, j);
+ xscale_send_u32(target, buf_get_u32(r->value, 0, 32));
+ r->dirty = false;
+ }
- if ((armv4_5_number_to_mode(i) != ARMV4_5_MODE_USR) && (armv4_5_number_to_mode(i) != ARMV4_5_MODE_SYS))
- {
- xscale_send_u32(target, buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 16).value, 0, 32));
- ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), 16).dirty = 0;
- }
+ /* send spsr if not in USR/SYS mode */
+ if (mode != ARMV4_5_MODE_SYS) {
+ r = &ARMV4_5_CORE_REG_MODE(armv4_5->core_cache,
+ mode, 16);
+ xscale_send_u32(target, buf_get_u32(r->value, 0, 32));
+ r->dirty = false;
}
}
armv4_5 = &xscale->armv4_5_common;
- /* store architecture specfic data (none so far) */
+ /* store architecture specfic data */
xscale->common_magic = XSCALE_COMMON_MAGIC;
- /* we don't really *need* variant info ... */
+ /* we don't really *need* a variant param ... */
if (variant) {
int ir_length = 0;
|| strcmp(variant, "ixp45x") == 0
|| strcmp(variant, "ixp46x") == 0)
ir_length = 7;
+ else if (strcmp(variant, "pxa3xx") == 0)
+ ir_length = 11;
else
LOG_WARNING("%s: unrecognized variant %s",
tap->dotted_name, variant);
}
}
+ /* PXA3xx shifts the JTAG instructions */
+ if (tap->ir_length == 11)
+ xscale->xscale_variant = XSCALE_PXA3XX;
+ else
+ xscale->xscale_variant = XSCALE_IXP4XX_PXA2XX;
+
/* the debug handler isn't installed (and thus not running) at this time */
xscale->handler_address = 0xfe000800;