Attempt to discover XLEN with abstract reg reads
Change-Id: I7ce9c8c0c34bd875dba11596e6f6268320b2fb3a
This commit is contained in:
parent
5e3d9803ab
commit
e6221e75c9
|
@ -5,13 +5,6 @@
|
||||||
#define S0 8
|
#define S0 8
|
||||||
#define S1 9
|
#define S1 9
|
||||||
|
|
||||||
/*
|
|
||||||
* Disabling the warning we get when some opcodes functions aren't used. Not
|
|
||||||
* every user of this file uses every function, and it doesn't make sense to
|
|
||||||
* make them global. I suppose they could be macros.
|
|
||||||
*/
|
|
||||||
#pragma GCC diagnostic ignored "-Wunused-function"
|
|
||||||
|
|
||||||
static uint32_t bits(uint32_t value, unsigned int hi, unsigned int lo) {
|
static uint32_t bits(uint32_t value, unsigned int hi, unsigned int lo) {
|
||||||
return (value >> lo) & ((1 << (hi+1-lo)) - 1);
|
return (value >> lo) & ((1 << (hi+1-lo)) - 1);
|
||||||
}
|
}
|
||||||
|
@ -20,6 +13,7 @@ static uint32_t bit(uint32_t value, unsigned int b) {
|
||||||
return (value >> b) & 1;
|
return (value >> b) & 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t jal(unsigned int rd, uint32_t imm) __attribute__ ((unused));
|
||||||
static uint32_t jal(unsigned int rd, uint32_t imm) {
|
static uint32_t jal(unsigned int rd, uint32_t imm) {
|
||||||
return (bit(imm, 20) << 31) |
|
return (bit(imm, 20) << 31) |
|
||||||
(bits(imm, 10, 1) << 21) |
|
(bits(imm, 10, 1) << 21) |
|
||||||
|
@ -29,12 +23,14 @@ static uint32_t jal(unsigned int rd, uint32_t imm) {
|
||||||
MATCH_JAL;
|
MATCH_JAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t csrsi(unsigned int csr, uint16_t imm) __attribute__ ((unused));
|
||||||
static uint32_t csrsi(unsigned int csr, uint16_t imm) {
|
static uint32_t csrsi(unsigned int csr, uint16_t imm) {
|
||||||
return (csr << 20) |
|
return (csr << 20) |
|
||||||
(bits(imm, 4, 0) << 15) |
|
(bits(imm, 4, 0) << 15) |
|
||||||
MATCH_CSRRSI;
|
MATCH_CSRRSI;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t sw(unsigned int src, unsigned int base, uint16_t offset) __attribute__ ((unused));
|
||||||
static uint32_t sw(unsigned int src, unsigned int base, uint16_t offset)
|
static uint32_t sw(unsigned int src, unsigned int base, uint16_t offset)
|
||||||
{
|
{
|
||||||
return (bits(offset, 11, 5) << 25) |
|
return (bits(offset, 11, 5) << 25) |
|
||||||
|
@ -44,6 +40,7 @@ static uint32_t sw(unsigned int src, unsigned int base, uint16_t offset)
|
||||||
MATCH_SW;
|
MATCH_SW;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t sd(unsigned int src, unsigned int base, uint16_t offset) __attribute__ ((unused));
|
||||||
static uint32_t sd(unsigned int src, unsigned int base, uint16_t offset)
|
static uint32_t sd(unsigned int src, unsigned int base, uint16_t offset)
|
||||||
{
|
{
|
||||||
return (bits(offset, 11, 5) << 25) |
|
return (bits(offset, 11, 5) << 25) |
|
||||||
|
@ -53,6 +50,7 @@ static uint32_t sd(unsigned int src, unsigned int base, uint16_t offset)
|
||||||
MATCH_SD;
|
MATCH_SD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t sh(unsigned int src, unsigned int base, uint16_t offset) __attribute__ ((unused));
|
||||||
static uint32_t sh(unsigned int src, unsigned int base, uint16_t offset)
|
static uint32_t sh(unsigned int src, unsigned int base, uint16_t offset)
|
||||||
{
|
{
|
||||||
return (bits(offset, 11, 5) << 25) |
|
return (bits(offset, 11, 5) << 25) |
|
||||||
|
@ -62,6 +60,7 @@ static uint32_t sh(unsigned int src, unsigned int base, uint16_t offset)
|
||||||
MATCH_SH;
|
MATCH_SH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t sb(unsigned int src, unsigned int base, uint16_t offset) __attribute__ ((unused));
|
||||||
static uint32_t sb(unsigned int src, unsigned int base, uint16_t offset)
|
static uint32_t sb(unsigned int src, unsigned int base, uint16_t offset)
|
||||||
{
|
{
|
||||||
return (bits(offset, 11, 5) << 25) |
|
return (bits(offset, 11, 5) << 25) |
|
||||||
|
@ -71,6 +70,7 @@ static uint32_t sb(unsigned int src, unsigned int base, uint16_t offset)
|
||||||
MATCH_SB;
|
MATCH_SB;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t ld(unsigned int rd, unsigned int base, uint16_t offset) __attribute__ ((unused));
|
||||||
static uint32_t ld(unsigned int rd, unsigned int base, uint16_t offset)
|
static uint32_t ld(unsigned int rd, unsigned int base, uint16_t offset)
|
||||||
{
|
{
|
||||||
return (bits(offset, 11, 0) << 20) |
|
return (bits(offset, 11, 0) << 20) |
|
||||||
|
@ -79,6 +79,7 @@ static uint32_t ld(unsigned int rd, unsigned int base, uint16_t offset)
|
||||||
MATCH_LD;
|
MATCH_LD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t lw(unsigned int rd, unsigned int base, uint16_t offset) __attribute__ ((unused));
|
||||||
static uint32_t lw(unsigned int rd, unsigned int base, uint16_t offset)
|
static uint32_t lw(unsigned int rd, unsigned int base, uint16_t offset)
|
||||||
{
|
{
|
||||||
return (bits(offset, 11, 0) << 20) |
|
return (bits(offset, 11, 0) << 20) |
|
||||||
|
@ -87,6 +88,7 @@ static uint32_t lw(unsigned int rd, unsigned int base, uint16_t offset)
|
||||||
MATCH_LW;
|
MATCH_LW;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t lh(unsigned int rd, unsigned int base, uint16_t offset) __attribute__ ((unused));
|
||||||
static uint32_t lh(unsigned int rd, unsigned int base, uint16_t offset)
|
static uint32_t lh(unsigned int rd, unsigned int base, uint16_t offset)
|
||||||
{
|
{
|
||||||
return (bits(offset, 11, 0) << 20) |
|
return (bits(offset, 11, 0) << 20) |
|
||||||
|
@ -95,6 +97,7 @@ static uint32_t lh(unsigned int rd, unsigned int base, uint16_t offset)
|
||||||
MATCH_LH;
|
MATCH_LH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t lb(unsigned int rd, unsigned int base, uint16_t offset) __attribute__ ((unused));
|
||||||
static uint32_t lb(unsigned int rd, unsigned int base, uint16_t offset)
|
static uint32_t lb(unsigned int rd, unsigned int base, uint16_t offset)
|
||||||
{
|
{
|
||||||
return (bits(offset, 11, 0) << 20) |
|
return (bits(offset, 11, 0) << 20) |
|
||||||
|
@ -103,10 +106,12 @@ static uint32_t lb(unsigned int rd, unsigned int base, uint16_t offset)
|
||||||
MATCH_LB;
|
MATCH_LB;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t csrw(unsigned int source, unsigned int csr) __attribute__ ((unused));
|
||||||
static uint32_t csrw(unsigned int source, unsigned int csr) {
|
static uint32_t csrw(unsigned int source, unsigned int csr) {
|
||||||
return (csr << 20) | (source << 15) | MATCH_CSRRW;
|
return (csr << 20) | (source << 15) | MATCH_CSRRW;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t addi(unsigned int dest, unsigned int src, uint16_t imm) __attribute__ ((unused));
|
||||||
static uint32_t addi(unsigned int dest, unsigned int src, uint16_t imm)
|
static uint32_t addi(unsigned int dest, unsigned int src, uint16_t imm)
|
||||||
{
|
{
|
||||||
return (bits(imm, 11, 0) << 20) |
|
return (bits(imm, 11, 0) << 20) |
|
||||||
|
@ -115,10 +120,12 @@ static uint32_t addi(unsigned int dest, unsigned int src, uint16_t imm)
|
||||||
MATCH_ADDI;
|
MATCH_ADDI;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t csrr(unsigned int rd, unsigned int csr) __attribute__ ((unused));
|
||||||
static uint32_t csrr(unsigned int rd, unsigned int csr) {
|
static uint32_t csrr(unsigned int rd, unsigned int csr) {
|
||||||
return (csr << 20) | (rd << 7) | MATCH_CSRRS;
|
return (csr << 20) | (rd << 7) | MATCH_CSRRS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t fsw(unsigned int src, unsigned int base, uint16_t offset) __attribute__ ((unused));
|
||||||
static uint32_t fsw(unsigned int src, unsigned int base, uint16_t offset)
|
static uint32_t fsw(unsigned int src, unsigned int base, uint16_t offset)
|
||||||
{
|
{
|
||||||
return (bits(offset, 11, 5) << 25) |
|
return (bits(offset, 11, 5) << 25) |
|
||||||
|
@ -128,6 +135,7 @@ static uint32_t fsw(unsigned int src, unsigned int base, uint16_t offset)
|
||||||
MATCH_FSW;
|
MATCH_FSW;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t fsd(unsigned int src, unsigned int base, uint16_t offset) __attribute__ ((unused));
|
||||||
static uint32_t fsd(unsigned int src, unsigned int base, uint16_t offset)
|
static uint32_t fsd(unsigned int src, unsigned int base, uint16_t offset)
|
||||||
{
|
{
|
||||||
return (bits(offset, 11, 5) << 25) |
|
return (bits(offset, 11, 5) << 25) |
|
||||||
|
@ -137,6 +145,7 @@ static uint32_t fsd(unsigned int src, unsigned int base, uint16_t offset)
|
||||||
MATCH_FSD;
|
MATCH_FSD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t flw(unsigned int dest, unsigned int base, uint16_t offset) __attribute__ ((unused));
|
||||||
static uint32_t flw(unsigned int dest, unsigned int base, uint16_t offset)
|
static uint32_t flw(unsigned int dest, unsigned int base, uint16_t offset)
|
||||||
{
|
{
|
||||||
return (bits(offset, 11, 0) << 20) |
|
return (bits(offset, 11, 0) << 20) |
|
||||||
|
@ -145,6 +154,7 @@ static uint32_t flw(unsigned int dest, unsigned int base, uint16_t offset)
|
||||||
MATCH_FLW;
|
MATCH_FLW;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t fld(unsigned int dest, unsigned int base, uint16_t offset) __attribute__ ((unused));
|
||||||
static uint32_t fld(unsigned int dest, unsigned int base, uint16_t offset)
|
static uint32_t fld(unsigned int dest, unsigned int base, uint16_t offset)
|
||||||
{
|
{
|
||||||
return (bits(offset, 11, 0) << 20) |
|
return (bits(offset, 11, 0) << 20) |
|
||||||
|
@ -153,15 +163,19 @@ static uint32_t fld(unsigned int dest, unsigned int base, uint16_t offset)
|
||||||
MATCH_FLD;
|
MATCH_FLD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t ebreak(void) __attribute__ ((unused));
|
||||||
static uint32_t ebreak(void) { return MATCH_EBREAK; }
|
static uint32_t ebreak(void) { return MATCH_EBREAK; }
|
||||||
|
static uint32_t ebreak_c(void) __attribute__ ((unused));
|
||||||
static uint32_t ebreak_c(void) { return MATCH_C_EBREAK; }
|
static uint32_t ebreak_c(void) { return MATCH_C_EBREAK; }
|
||||||
|
|
||||||
|
static uint32_t fence_i(void) __attribute__ ((unused));
|
||||||
static uint32_t fence_i(void)
|
static uint32_t fence_i(void)
|
||||||
{
|
{
|
||||||
return MATCH_FENCE_I;
|
return MATCH_FENCE_I;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
static uint32_t lui(unsigned int dest, uint32_t imm) __attribute__ ((unused));
|
||||||
static uint32_t lui(unsigned int dest, uint32_t imm)
|
static uint32_t lui(unsigned int dest, uint32_t imm)
|
||||||
{
|
{
|
||||||
return (bits(imm, 19, 0) << 12) |
|
return (bits(imm, 19, 0) << 12) |
|
||||||
|
@ -169,17 +183,20 @@ static uint32_t lui(unsigned int dest, uint32_t imm)
|
||||||
MATCH_LUI;
|
MATCH_LUI;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t csrci(unsigned int csr, uint16_t imm) __attribute__ ((unused));
|
||||||
static uint32_t csrci(unsigned int csr, uint16_t imm) {
|
static uint32_t csrci(unsigned int csr, uint16_t imm) {
|
||||||
return (csr << 20) |
|
return (csr << 20) |
|
||||||
(bits(imm, 4, 0) << 15) |
|
(bits(imm, 4, 0) << 15) |
|
||||||
MATCH_CSRRCI;
|
MATCH_CSRRCI;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t li(unsigned int dest, uint16_t imm) __attribute__ ((unused));
|
||||||
static uint32_t li(unsigned int dest, uint16_t imm)
|
static uint32_t li(unsigned int dest, uint16_t imm)
|
||||||
{
|
{
|
||||||
return addi(dest, 0, imm);
|
return addi(dest, 0, imm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t fsd(unsigned int src, unsigned int base, uint16_t offset) __attribute__ ((unused));
|
||||||
static uint32_t fsd(unsigned int src, unsigned int base, uint16_t offset)
|
static uint32_t fsd(unsigned int src, unsigned int base, uint16_t offset)
|
||||||
{
|
{
|
||||||
return (bits(offset, 11, 5) << 25) |
|
return (bits(offset, 11, 5) << 25) |
|
||||||
|
@ -189,6 +206,7 @@ static uint32_t fsd(unsigned int src, unsigned int base, uint16_t offset)
|
||||||
MATCH_FSD;
|
MATCH_FSD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t ori(unsigned int dest, unsigned int src, uint16_t imm) __attribute__ ((unused));
|
||||||
static uint32_t ori(unsigned int dest, unsigned int src, uint16_t imm)
|
static uint32_t ori(unsigned int dest, unsigned int src, uint16_t imm)
|
||||||
{
|
{
|
||||||
return (bits(imm, 11, 0) << 20) |
|
return (bits(imm, 11, 0) << 20) |
|
||||||
|
@ -197,12 +215,14 @@ static uint32_t ori(unsigned int dest, unsigned int src, uint16_t imm)
|
||||||
MATCH_ORI;
|
MATCH_ORI;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t nop(void) __attribute__ ((unused));
|
||||||
static uint32_t nop(void)
|
static uint32_t nop(void)
|
||||||
{
|
{
|
||||||
return addi(0, 0, 0);
|
return addi(0, 0, 0);
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
static uint32_t xori(unsigned int dest, unsigned int src, uint16_t imm) __attribute__ ((unused));
|
||||||
static uint32_t xori(unsigned int dest, unsigned int src, uint16_t imm)
|
static uint32_t xori(unsigned int dest, unsigned int src, uint16_t imm)
|
||||||
{
|
{
|
||||||
return (bits(imm, 11, 0) << 20) |
|
return (bits(imm, 11, 0) << 20) |
|
||||||
|
@ -211,6 +231,7 @@ static uint32_t xori(unsigned int dest, unsigned int src, uint16_t imm)
|
||||||
MATCH_XORI;
|
MATCH_XORI;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t srli(unsigned int dest, unsigned int src, uint8_t shamt) __attribute__ ((unused));
|
||||||
static uint32_t srli(unsigned int dest, unsigned int src, uint8_t shamt)
|
static uint32_t srli(unsigned int dest, unsigned int src, uint8_t shamt)
|
||||||
{
|
{
|
||||||
return (bits(shamt, 4, 0) << 20) |
|
return (bits(shamt, 4, 0) << 20) |
|
||||||
|
|
|
@ -468,6 +468,7 @@ static uint64_t dbus_read(struct target *target, uint16_t address)
|
||||||
uint16_t address_in;
|
uint16_t address_in;
|
||||||
|
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
|
dbus_scan(target, &address_in, &value, DBUS_OP_READ, address, 0);
|
||||||
do {
|
do {
|
||||||
status = dbus_scan(target, &address_in, &value, DBUS_OP_READ, address, 0);
|
status = dbus_scan(target, &address_in, &value, DBUS_OP_READ, address, 0);
|
||||||
if (status == DBUS_STATUS_BUSY) {
|
if (status == DBUS_STATUS_BUSY) {
|
||||||
|
@ -725,19 +726,6 @@ static int wait_for_debugint_clear(struct target *target, bool ignore_first)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dram_check32(struct target *target, unsigned int index,
|
|
||||||
uint32_t expected)
|
|
||||||
{
|
|
||||||
uint16_t address = dram_address(index);
|
|
||||||
uint32_t actual = dbus_read(target, address);
|
|
||||||
if (expected != actual) {
|
|
||||||
LOG_ERROR("Wrote 0x%x to Debug RAM at %d, but read back 0x%x",
|
|
||||||
expected, index, actual);
|
|
||||||
return ERROR_FAIL;
|
|
||||||
}
|
|
||||||
return ERROR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void cache_set32(struct target *target, unsigned int index, uint32_t data)
|
static void cache_set32(struct target *target, unsigned int index, uint32_t data)
|
||||||
{
|
{
|
||||||
riscv013_info_t *info = get_info(target);
|
riscv013_info_t *info = get_info(target);
|
||||||
|
@ -813,27 +801,6 @@ static void cache_clean(struct target *target)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cache_check(struct target *target)
|
|
||||||
{
|
|
||||||
riscv013_info_t *info = get_info(target);
|
|
||||||
int error = 0;
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < info->dramsize; i++) {
|
|
||||||
if (info->dram_cache[i].valid && !info->dram_cache[i].dirty) {
|
|
||||||
if (dram_check32(target, i, info->dram_cache[i].data) != ERROR_OK) {
|
|
||||||
error++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
dump_debug_ram(target);
|
|
||||||
return ERROR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ERROR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Write cache to the target, and optionally run the program.
|
/** Write cache to the target, and optionally run the program.
|
||||||
* Then read the value at address into the cache, assuming address < 128. */
|
* Then read the value at address into the cache, assuming address < 128. */
|
||||||
#define CACHE_NO_READ 128
|
#define CACHE_NO_READ 128
|
||||||
|
@ -1770,6 +1737,70 @@ static int step(struct target *target, int current, uint32_t address,
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int abstract_read_register(struct target *target,
|
||||||
|
unsigned reg_number,
|
||||||
|
unsigned width,
|
||||||
|
uint64_t *result)
|
||||||
|
{
|
||||||
|
uint32_t command = 0;
|
||||||
|
switch (width) {
|
||||||
|
case 32:
|
||||||
|
command = set_field(command, AC_ACCESS_REGISTER_SIZE, 2);
|
||||||
|
break;
|
||||||
|
case 64:
|
||||||
|
command = set_field(command, AC_ACCESS_REGISTER_SIZE, 3);
|
||||||
|
break;
|
||||||
|
case 128:
|
||||||
|
command = set_field(command, AC_ACCESS_REGISTER_SIZE, 4);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOG_ERROR("Unsupported register width: %d", width);
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reg_number <= REG_XPR31) {
|
||||||
|
command |= reg_number + 0x1000 - REG_XPR0;
|
||||||
|
} else if (reg_number >= REG_CSR0 && reg_number <= REG_CSR4095) {
|
||||||
|
command |= reg_number - REG_CSR0;
|
||||||
|
} else if (reg_number >= REG_FPR0 && reg_number <= REG_FPR31) {
|
||||||
|
command |= reg_number + 0x1020 - REG_FPR0;
|
||||||
|
}
|
||||||
|
|
||||||
|
dbus_write(target, DMI_COMMAND, command);
|
||||||
|
|
||||||
|
uint32_t abstractcs;
|
||||||
|
for (unsigned i = 0; i < 256; i++) {
|
||||||
|
abstractcs = dbus_read(target, DMI_ABSTRACTCS);
|
||||||
|
if (get_field(abstractcs, DMI_ABSTRACTCS_BUSY) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (get_field(abstractcs, DMI_ABSTRACTCS_BUSY)) {
|
||||||
|
LOG_ERROR("Abstract command 0x%x never completed (abstractcs=0x%x)",
|
||||||
|
command, abstractcs);
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
if (get_field(abstractcs, DMI_ABSTRACTCS_CMDERR)) {
|
||||||
|
LOG_DEBUG("Abstract command 0x%x ended in error (abstractcs=0x%x)",
|
||||||
|
command, abstractcs);
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result) {
|
||||||
|
*result = 0;
|
||||||
|
switch (width) {
|
||||||
|
case 128:
|
||||||
|
LOG_WARNING("Ignoring top 64 bits from 128-bit register read.");
|
||||||
|
case 64:
|
||||||
|
*result |= ((uint64_t) dbus_read(target, DMI_DATA0)) << 32;
|
||||||
|
case 32:
|
||||||
|
*result |= dbus_read(target, DMI_DATA0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
static int examine(struct target *target)
|
static int examine(struct target *target)
|
||||||
{
|
{
|
||||||
// Don't need to select dbus, since the first thing we do is read dtmcontrol.
|
// Don't need to select dbus, since the first thing we do is read dtmcontrol.
|
||||||
|
@ -1802,6 +1833,17 @@ static int examine(struct target *target)
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t dmcontrol = dbus_read(target, DMI_DMCONTROL);
|
uint32_t dmcontrol = dbus_read(target, DMI_DMCONTROL);
|
||||||
|
if (get_field(dmcontrol, DMI_DMCONTROL_VERSION) != 1) {
|
||||||
|
LOG_ERROR("OpenOCD only supports Debug Module version 1, not %d "
|
||||||
|
"(dmcontrol=0x%x)", get_field(dmcontrol, DMI_DMCONTROL_VERSION), dmcontrol);
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset the Debug Module.
|
||||||
|
dbus_write(target, DMI_DMCONTROL, 0);
|
||||||
|
dbus_write(target, DMI_DMCONTROL, DMI_DMCONTROL_DMACTIVE);
|
||||||
|
dmcontrol = dbus_read(target, DMI_DMCONTROL);
|
||||||
|
|
||||||
LOG_DEBUG("dmcontrol: 0x%08x", dmcontrol);
|
LOG_DEBUG("dmcontrol: 0x%08x", dmcontrol);
|
||||||
LOG_DEBUG(" haltreq=%d", get_field(dmcontrol, DMI_DMCONTROL_HALTREQ));
|
LOG_DEBUG(" haltreq=%d", get_field(dmcontrol, DMI_DMCONTROL_HALTREQ));
|
||||||
LOG_DEBUG(" reset=%d", get_field(dmcontrol, DMI_DMCONTROL_RESET));
|
LOG_DEBUG(" reset=%d", get_field(dmcontrol, DMI_DMCONTROL_RESET));
|
||||||
|
@ -1813,9 +1855,9 @@ static int examine(struct target *target)
|
||||||
LOG_DEBUG(" authtype=%d", get_field(dmcontrol, DMI_DMCONTROL_AUTHTYPE));
|
LOG_DEBUG(" authtype=%d", get_field(dmcontrol, DMI_DMCONTROL_AUTHTYPE));
|
||||||
LOG_DEBUG(" version=%d", get_field(dmcontrol, DMI_DMCONTROL_VERSION));
|
LOG_DEBUG(" version=%d", get_field(dmcontrol, DMI_DMCONTROL_VERSION));
|
||||||
|
|
||||||
if (get_field(dmcontrol, DMI_DMCONTROL_VERSION) != 1) {
|
if (!get_field(dmcontrol, DMI_DMCONTROL_DMACTIVE)) {
|
||||||
LOG_ERROR("OpenOCD only supports Debug Module version 1, not %d "
|
LOG_ERROR("Debug Module did not become active. dmcontrol=0x%x",
|
||||||
"(dmcontrol=0x%x)", get_field(dmcontrol, DMI_DMCONTROL_VERSION), dmcontrol);
|
dmcontrol);
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1878,46 +1920,15 @@ static int examine(struct target *target)
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Figure out XLEN, and test writing all of Debug RAM while we're at it.
|
|
||||||
cache_set32(target, 0, xori(S1, ZERO, -1));
|
|
||||||
// 0xffffffff 0xffffffff:ffffffff 0xffffffff:ffffffff:ffffffff:ffffffff
|
|
||||||
cache_set32(target, 1, srli(S1, S1, 31));
|
|
||||||
// 0x00000001 0x00000001:ffffffff 0x00000001:ffffffff:ffffffff:ffffffff
|
|
||||||
cache_set32(target, 2, sw(S1, ZERO, DEBUG_RAM_START));
|
|
||||||
cache_set32(target, 3, srli(S1, S1, 31));
|
|
||||||
// 0x00000000 0x00000000:00000003 0x00000000:00000003:ffffffff:ffffffff
|
|
||||||
cache_set32(target, 4, sw(S1, ZERO, DEBUG_RAM_START + 4));
|
|
||||||
cache_set_jump(target, 5);
|
|
||||||
for (unsigned i = 6; i < info->dramsize; i++) {
|
|
||||||
cache_set32(target, i, i * 0x01020304);
|
|
||||||
}
|
|
||||||
|
|
||||||
cache_write(target, 0, false);
|
|
||||||
|
|
||||||
// Check that we can actually read/write dram.
|
|
||||||
if (cache_check(target) != ERROR_OK) {
|
|
||||||
return ERROR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
cache_write(target, 0, true);
|
|
||||||
cache_invalidate(target);
|
|
||||||
|
|
||||||
uint32_t word0 = cache_get32(target, 0);
|
|
||||||
uint32_t word1 = cache_get32(target, 1);
|
|
||||||
riscv_info_t *generic_info = (riscv_info_t *) target->arch_info;
|
riscv_info_t *generic_info = (riscv_info_t *) target->arch_info;
|
||||||
if (word0 == 1 && word1 == 0) {
|
if (abstract_read_register(target, 15, 128, NULL) == ERROR_OK) {
|
||||||
generic_info->xlen = 32;
|
|
||||||
} else if (word0 == 0xffffffff && word1 == 3) {
|
|
||||||
generic_info->xlen = 64;
|
|
||||||
} else if (word0 == 0xffffffff && word1 == 0xffffffff) {
|
|
||||||
generic_info->xlen = 128;
|
generic_info->xlen = 128;
|
||||||
} else {
|
} else if (abstract_read_register(target, 15, 64, NULL) == ERROR_OK) {
|
||||||
uint32_t exception = cache_get32(target, info->dramsize-1);
|
generic_info->xlen = 64;
|
||||||
LOG_ERROR("Failed to discover xlen; word0=0x%x, word1=0x%x, exception=0x%x",
|
} else if (abstract_read_register(target, 15, 32, NULL) == ERROR_OK) {
|
||||||
word0, word1, exception);
|
generic_info->xlen = 32;
|
||||||
dump_debug_ram(target);
|
|
||||||
return ERROR_FAIL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_DEBUG("Discovered XLEN is %d", xlen(target));
|
LOG_DEBUG("Discovered XLEN is %d", xlen(target));
|
||||||
|
|
||||||
// Update register list to match discovered XLEN.
|
// Update register list to match discovered XLEN.
|
||||||
|
|
|
@ -223,33 +223,6 @@ static uint32_t dtmcontrol_scan(struct target *target, uint32_t out)
|
||||||
return in;
|
return in;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t idcode_scan(struct target *target)
|
|
||||||
{
|
|
||||||
struct scan_field field;
|
|
||||||
uint8_t in_value[4];
|
|
||||||
|
|
||||||
jtag_add_ir_scan(target->tap, &select_idcode, TAP_IDLE);
|
|
||||||
|
|
||||||
field.num_bits = 32;
|
|
||||||
field.out_value = NULL;
|
|
||||||
field.in_value = in_value;
|
|
||||||
jtag_add_dr_scan(target->tap, 1, &field, TAP_IDLE);
|
|
||||||
|
|
||||||
int retval = jtag_execute_queue();
|
|
||||||
if (retval != ERROR_OK) {
|
|
||||||
LOG_ERROR("failed jtag scan: %d", retval);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Always return to dbus. */
|
|
||||||
jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE);
|
|
||||||
|
|
||||||
uint32_t in = buf_get_u32(field.in_value, 0, 32);
|
|
||||||
LOG_DEBUG("IDCODE: 0x0 -> 0x%x", in);
|
|
||||||
|
|
||||||
return in;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct target_type *get_target_type(struct target *target)
|
static struct target_type *get_target_type(struct target *target)
|
||||||
{
|
{
|
||||||
riscv_info_t *info = (riscv_info_t *) target->arch_info;
|
riscv_info_t *info = (riscv_info_t *) target->arch_info;
|
||||||
|
|
|
@ -27,6 +27,8 @@ extern struct scan_field select_idcode;
|
||||||
|
|
||||||
/*** Version-independent functions that we don't want in the main address space. ***/
|
/*** Version-independent functions that we don't want in the main address space. ***/
|
||||||
|
|
||||||
|
static uint32_t load(const struct target *target, unsigned int rd,
|
||||||
|
unsigned int base, uint16_t offset) __attribute__ ((unused));
|
||||||
static uint32_t load(const struct target *target, unsigned int rd,
|
static uint32_t load(const struct target *target, unsigned int rd,
|
||||||
unsigned int base, uint16_t offset)
|
unsigned int base, uint16_t offset)
|
||||||
{
|
{
|
||||||
|
@ -40,6 +42,8 @@ static uint32_t load(const struct target *target, unsigned int rd,
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t store(const struct target *target, unsigned int src,
|
||||||
|
unsigned int base, uint16_t offset) __attribute__ ((unused));
|
||||||
static uint32_t store(const struct target *target, unsigned int src,
|
static uint32_t store(const struct target *target, unsigned int src,
|
||||||
unsigned int base, uint16_t offset)
|
unsigned int base, uint16_t offset)
|
||||||
{
|
{
|
||||||
|
@ -53,6 +57,7 @@ static uint32_t store(const struct target *target, unsigned int src,
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned xlen(const struct target *target) __attribute__ ((unused));
|
||||||
static unsigned xlen(const struct target *target)
|
static unsigned xlen(const struct target *target)
|
||||||
{
|
{
|
||||||
riscv_info_t *info = (riscv_info_t *) target->arch_info;
|
riscv_info_t *info = (riscv_info_t *) target->arch_info;
|
||||||
|
|
Loading…
Reference in New Issue