openocd/src/target/xscale.h

178 lines
4.1 KiB
C
Raw Normal View History

/* SPDX-License-Identifier: GPL-2.0-or-later */
/***************************************************************************
* Copyright (C) 2005 by Dominic Rath *
* Dominic.Rath@gmx.de *
* *
* Copyright (C) 2007,2008 Øyvind Harboe *
* oyvind.harboe@zylin.com *
***************************************************************************/
#ifndef OPENOCD_TARGET_XSCALE_H
#define OPENOCD_TARGET_XSCALE_H
#include "arm.h"
#include "armv4_5_mmu.h"
#include "trace.h"
#define XSCALE_COMMON_MAGIC 0x58534341U
/* These four JTAG instructions are architecturally defined.
* Lengths are core-specific; originally 5 bits, later 7.
*/
#define XSCALE_DBGRX 0x02
#define XSCALE_DBGTX 0x10
#define XSCALE_LDIC 0x07
#define XSCALE_SELDCSR 0x09
/* Possible CPU types */
#define XSCALE_IXP4XX_PXA2XX 0x0
#define XSCALE_PXA3XX 0x4
enum xscale_debug_reason {
XSCALE_DBG_REASON_GENERIC,
XSCALE_DBG_REASON_RESET,
XSCALE_DBG_REASON_TB_FULL,
};
enum xscale_trace_entry_type {
XSCALE_TRACE_MESSAGE = 0x0,
XSCALE_TRACE_ADDRESS = 0x1,
};
struct xscale_trace_entry {
uint8_t data;
enum xscale_trace_entry_type type;
};
struct xscale_trace_data {
struct xscale_trace_entry *entries;
int depth;
uint32_t chkpt0;
uint32_t chkpt1;
uint32_t last_instruction;
xscale: fix analyze_trace for trace data collected in wrap mode This patch fixes the xscale_analyze_trace() function. This function was defective for a trace collected in 'fill' mode (hiccups with repeated instructions) and completely broken when buffer overflowed in 'wrap' mode. The reason for the latter case is that the checkpoint registers were interpreted incorrectly when two checkpoints are present in the trace (which will be true in 'wrap' mode once the buffer fills). In this case, checkpoint1 register will contain the older entry, and checkpoint0 the newer. The original code assumed the opposite. I eventually gave up trying to understand all the logic of the function, and rewrote it. I think it's much cleaner and understandable now. I have been using and testing this for a few weeks now. I'm confident it hasn't regressed in any way. Also added capability to handle (as best as possible) the case where an instruction can not be read from the loaded trace image; e.g., partial image. This was a 'TODO' comment in the original xscale_analyze_trace(). Outside of xcsale_analyze_trace(), these (related) changes were made: - Remove pc_ok and current_pc elements from struct xscale_trace. These elements and associated logic are useless clutter because the very first entry placed in the trace buffer is always an indirect jump to the address at which execution resumed. This type of trace entry includes the literal address in the trace buffer, so the initial address of the trace is immediately determined from the trace buffer contents and does not need to be recorded when trace is enabled. - Added num_checkpoints to struct xscale_trace_data, which is necessary in order to correctly interpret the checkpoint register contents. - In xscale_read_trace() - Fix potential array out-of-bounds condition. - Eliminate partial address entries when parsing trace (can occur in wrap mode). - Count and record number of checkpoints in trace. - Added small, inlined utility function xscale_display_instruction() to help make the code more concise and clear. TODO: - Save processor state (arm or thumb) in struct xscale_trace when trace is enabled so that trace can be analyzed correctly (currently assumes arm mode). - Add element to struct xscale_trace that records (when trace is enabled) whether vector table is relocated high (to 0xffff0000) or not, so that a branch to an exception vector is traced correctly (curently assumes vectors at 0x0).
2010-04-13 17:34:52 +00:00
unsigned int num_checkpoints;
struct xscale_trace_data *next;
};
enum trace_mode {
XSCALE_TRACE_DISABLED,
XSCALE_TRACE_FILL,
XSCALE_TRACE_WRAP
};
struct xscale_trace {
struct image *image; /* source for target opcodes */
struct xscale_trace_data *data; /* linked list of collected trace data */
int buffer_fill; /* maximum number of trace runs to read */
int fill_counter; /* running count during trace collection */
enum trace_mode mode;
enum arm_state core_state; /* current core state (ARM, Thumb) */
};
struct xscale_common {
unsigned int common_magic;
/* armv4/5 common stuff */
struct arm arm;
/* XScale registers (CP15, DBG) */
struct reg_cache *reg_cache;
/* current state of the debug handler */
uint32_t handler_address;
/* target-endian buffers with exception vectors */
uint32_t low_vectors[8];
uint32_t high_vectors[8];
/* static low vectors */
uint8_t static_low_vectors_set; /* bit field with static vectors set by the user */
uint8_t static_high_vectors_set; /* bit field with static vectors set by the user */
uint32_t static_low_vectors[8];
uint32_t static_high_vectors[8];
/* DCache cleaning */
uint32_t cache_clean_address;
/* whether hold_rst and ext_dbg_break should be set */
int hold_rst;
int external_debug_break;
/* breakpoint / watchpoint handling */
int dbr_available;
int dbr0_used;
int dbr1_used;
int ibcr_available;
int ibcr0_used;
int ibcr1_used;
uint32_t arm_bkpt;
uint16_t thumb_bkpt;
uint8_t vector_catch;
struct xscale_trace trace;
int arch_debug_reason;
/* MMU/Caches */
struct armv4_5_mmu_common armv4_5_mmu;
uint32_t cp15_control_reg;
int fast_memory_access;
/* CPU variant */
int xscale_variant;
};
static inline struct xscale_common *
target_to_xscale(struct target *target)
{
return container_of(target->arch_info, struct xscale_common, arm);
}
struct xscale_reg {
int dbg_handler_number;
struct target *target;
};
enum {
XSCALE_MAINID, /* 0 */
XSCALE_CACHETYPE,
XSCALE_CTRL,
XSCALE_AUXCTRL,
XSCALE_TTB,
XSCALE_DAC,
XSCALE_FSR,
XSCALE_FAR,
XSCALE_PID,
XSCALE_CPACCESS,
XSCALE_IBCR0, /* 10 */
XSCALE_IBCR1,
XSCALE_DBR0,
XSCALE_DBR1,
XSCALE_DBCON,
XSCALE_TBREG,
XSCALE_CHKPT0,
XSCALE_CHKPT1,
XSCALE_DCSR,
XSCALE_TX,
XSCALE_RX, /* 20 */
XSCALE_TXRXCTRL,
};
#define ERROR_XSCALE_NO_TRACE_DATA (-700)
/* DCSR bit and field definitions */
#define DCSR_TR (1 << 16)
#define DCSR_TU (1 << 17)
#define DCSR_TS (1 << 18)
#define DCSR_TA (1 << 19)
#define DCSR_TD (1 << 20)
#define DCSR_TI (1 << 22)
#define DCSR_TF (1 << 23)
#define DCSR_TRAP_MASK \
(DCSR_TF | DCSR_TI | DCSR_TD | DCSR_TA | DCSR_TS | DCSR_TU | DCSR_TR)
#endif /* OPENOCD_TARGET_XSCALE_H */