WIP; doesn't work.
Change-Id: Ia407e82ccbd2044ad61e0845d285dd5765154476
This commit is contained in:
parent
77802af655
commit
94e8250713
|
@ -100,77 +100,6 @@ int riscv_program_exec(struct riscv_program *p, struct target *t)
|
|||
return ERROR_OK;
|
||||
}
|
||||
|
||||
riscv_addr_t riscv_program_alloc_data(struct riscv_program *p, size_t bytes)
|
||||
{
|
||||
riscv_addr_t addr =
|
||||
riscv_debug_buffer_addr(p->target)
|
||||
+ riscv_debug_buffer_size(p->target) * sizeof(p->debug_buffer[0])
|
||||
- p->data_count * sizeof(p->debug_buffer[0])
|
||||
- bytes;
|
||||
while (addr % bytes != 0) addr--;
|
||||
|
||||
riscv_addr_t ptop =
|
||||
riscv_debug_buffer_addr(p->target)
|
||||
+ p->instruction_count * sizeof(p->debug_buffer[0]);
|
||||
|
||||
if (addr <= ptop) {
|
||||
LOG_ERROR("unable to allocate %d bytes", (int)bytes);
|
||||
return RISCV_PROGRAM_ALLOC_FAIL;
|
||||
}
|
||||
|
||||
p->data_count =
|
||||
+ riscv_debug_buffer_size(p->target)
|
||||
- (addr - riscv_debug_buffer_addr(p->target)) / sizeof(p->debug_buffer[0]);
|
||||
return addr;
|
||||
}
|
||||
|
||||
riscv_addr_t riscv_program_alloc_x(struct riscv_program *p)
|
||||
{
|
||||
return riscv_program_alloc_data(p, p->target_xlen / 8);
|
||||
}
|
||||
|
||||
riscv_addr_t riscv_program_alloc_d(struct riscv_program *p)
|
||||
{
|
||||
return riscv_program_alloc_data(p, 8);
|
||||
}
|
||||
|
||||
riscv_addr_t riscv_program_alloc_w(struct riscv_program *p)
|
||||
{
|
||||
return riscv_program_alloc_data(p, 4);
|
||||
}
|
||||
|
||||
riscv_addr_t riscv_program_alloc_h(struct riscv_program *p)
|
||||
{
|
||||
return riscv_program_alloc_data(p, 2);
|
||||
}
|
||||
|
||||
riscv_addr_t riscv_program_alloc_b(struct riscv_program *p)
|
||||
{
|
||||
return riscv_program_alloc_data(p, 1);
|
||||
}
|
||||
|
||||
riscv_insn_t riscv_program_read_ram(struct riscv_program *p, riscv_addr_t addr)
|
||||
{
|
||||
if (addr < riscv_debug_buffer_addr(p->target))
|
||||
return -1;
|
||||
if ((size_t)addr > riscv_debug_buffer_addr(p->target) + (riscv_debug_buffer_size(p->target) * sizeof(p->debug_buffer[0])))
|
||||
return -1;
|
||||
|
||||
int off = (addr - riscv_debug_buffer_addr(p->target)) / sizeof(p->debug_buffer[0]);
|
||||
return p->debug_buffer[off];
|
||||
}
|
||||
|
||||
void riscv_program_write_ram(struct riscv_program *p, riscv_addr_t addr, uint64_t d)
|
||||
{
|
||||
if (addr < riscv_debug_buffer_addr(p->target))
|
||||
return;
|
||||
if ((size_t)addr > riscv_debug_buffer_addr(p->target) + (riscv_debug_buffer_size(p->target) * sizeof(p->debug_buffer[0])))
|
||||
return;
|
||||
|
||||
int off = (addr - riscv_debug_buffer_addr(p->target)) / sizeof(p->debug_buffer[0]);
|
||||
p->debug_buffer[off] = d;
|
||||
}
|
||||
|
||||
int riscv_program_swr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int offset)
|
||||
{
|
||||
p->writes_memory = 1;
|
||||
|
|
|
@ -60,22 +60,6 @@ int riscv_program_insert(struct riscv_program *p, riscv_insn_t i);
|
|||
* memory. */
|
||||
int riscv_program_save_to_dscratch(struct riscv_program *p, enum gdb_regno to_save);
|
||||
|
||||
/* Allocates data of various sizes. Either returns the absolute physical
|
||||
* address or RISCV_PROGRAM_ALLOC_FAIL on failure. */
|
||||
riscv_addr_t riscv_program_alloc_data(struct riscv_program *p, size_t bytes);
|
||||
riscv_addr_t riscv_program_alloc_x(struct riscv_program *p);
|
||||
riscv_addr_t riscv_program_alloc_d(struct riscv_program *p);
|
||||
riscv_addr_t riscv_program_alloc_w(struct riscv_program *p);
|
||||
riscv_addr_t riscv_program_alloc_h(struct riscv_program *p);
|
||||
riscv_addr_t riscv_program_alloc_b(struct riscv_program *p);
|
||||
#define RISCV_PROGRAM_ALLOC_FAIL ((riscv_addr_t)(-1))
|
||||
|
||||
/* Reads a word of memory from this program's internal view of the debug RAM.
|
||||
* This is what you want to use to get data back from the program after it
|
||||
* executes. */
|
||||
riscv_insn_t riscv_program_read_ram(struct riscv_program *p, riscv_addr_t addr);
|
||||
void riscv_program_write_ram(struct riscv_program *p, riscv_addr_t a, uint64_t d);
|
||||
|
||||
/* Helpers to assembly various instructions. Return 0 on success. These might
|
||||
* assembly into a multi-instruction sequence that overwrites some other
|
||||
* register, but those will be properly saved and restored. */
|
||||
|
|
|
@ -31,13 +31,13 @@
|
|||
|
||||
static void riscv013_on_step_or_resume(struct target *target, bool step);
|
||||
static void riscv013_step_or_resume_current_hart(struct target *target, bool step);
|
||||
static riscv_addr_t riscv013_progbuf_addr(struct target *target);
|
||||
static riscv_addr_t riscv013_data_size(struct target *target);
|
||||
static riscv_addr_t riscv013_data_addr(struct target *target);
|
||||
static void riscv013_set_autoexec(struct target *target, unsigned index,
|
||||
bool enabled);
|
||||
static int riscv013_debug_buffer_register(struct target *target, riscv_addr_t addr);
|
||||
static void riscv013_clear_abstract_error(struct target *target);
|
||||
//static riscv_addr_t riscv013_progbuf_addr(struct target *target);
|
||||
//static riscv_addr_t riscv013_data_size(struct target *target);
|
||||
//static riscv_addr_t riscv013_data_addr(struct target *target);
|
||||
//static void riscv013_set_autoexec(struct target *target, unsigned index,
|
||||
//bool enabled);
|
||||
//static int riscv013_debug_buffer_register(struct target *target, riscv_addr_t addr);
|
||||
//static void riscv013_clear_abstract_error(struct target *target);
|
||||
|
||||
/* Implementations of the functions in riscv_info_t. */
|
||||
static riscv_reg_t riscv013_get_register(struct target *target, int hartid, int regid);
|
||||
|
@ -517,6 +517,7 @@ static void dmi_write(struct target *target, uint16_t address, uint64_t value)
|
|||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void increase_ac_busy_delay(struct target *target)
|
||||
{
|
||||
riscv013_info_t *info = get_info(target);
|
||||
|
@ -525,6 +526,7 @@ static void increase_ac_busy_delay(struct target *target)
|
|||
info->dtmcontrol_idle, info->dmi_busy_delay,
|
||||
info->ac_busy_delay);
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32_t abstract_register_size(unsigned width)
|
||||
{
|
||||
|
@ -769,6 +771,8 @@ static int register_write_direct(struct target *target, unsigned number,
|
|||
|
||||
riscv_program_init(&program, target);
|
||||
|
||||
assert(0);
|
||||
#if 0
|
||||
riscv_addr_t input = riscv_program_alloc_d(&program);
|
||||
riscv_program_write_ram(&program, input + 4, value >> 32);
|
||||
riscv_program_write_ram(&program, input, value);
|
||||
|
@ -794,6 +798,7 @@ static int register_write_direct(struct target *target, unsigned number,
|
|||
}
|
||||
|
||||
return ERROR_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
/** Actually read registers from the target right now. */
|
||||
|
@ -805,6 +810,22 @@ static int register_read_direct(struct target *target, uint64_t *value, uint32_t
|
|||
if (result != ERROR_OK) {
|
||||
struct riscv_program program;
|
||||
riscv_program_init(&program, target);
|
||||
assert(0);
|
||||
assert(number != GDB_REGNO_S0);
|
||||
|
||||
uint64_t s0;
|
||||
if (register_read_direct(target, &s0, GDB_REGNO_S0) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
|
||||
// Write program to move data into s0.
|
||||
// Execute program.
|
||||
// Read S0
|
||||
if (register_read_direct(target, value, GDB_REGNO_S0) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
// Restore S0.
|
||||
if (register_write_direct(target, GDB_REGNO_S0, &s0) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
#if 0
|
||||
riscv_addr_t output = riscv_program_alloc_d(&program);
|
||||
riscv_program_write_ram(&program, output + 4, 0);
|
||||
riscv_program_write_ram(&program, output, 0);
|
||||
|
@ -833,6 +854,7 @@ static int register_read_direct(struct target *target, uint64_t *value, uint32_t
|
|||
*value = 0;
|
||||
*value |= ((uint64_t)(riscv_program_read_ram(&program, output + 4))) << 32;
|
||||
*value |= riscv_program_read_ram(&program, output);
|
||||
#endif
|
||||
}
|
||||
|
||||
LOG_DEBUG("[%d] reg[0x%x] = 0x%" PRIx64, riscv_current_hartid(target),
|
||||
|
@ -1080,77 +1102,19 @@ static int examine(struct target *target)
|
|||
r->debug_buffer_size[i] = info->progsize;
|
||||
|
||||
/* Guess this is a 32-bit system, we're probing it. */
|
||||
r->xlen[i] = 32;
|
||||
|
||||
/* First find the low 32 bits of the program buffer. This is
|
||||
* used to check for alignment. */
|
||||
struct riscv_program program32;
|
||||
riscv_program_init(&program32, target);
|
||||
riscv_program_csrrw(&program32, GDB_REGNO_S0, GDB_REGNO_S0, GDB_REGNO_DSCRATCH);
|
||||
riscv_program_insert(&program32, auipc(GDB_REGNO_S0));
|
||||
riscv_program_insert(&program32, sw(GDB_REGNO_S0, GDB_REGNO_S0, -4));
|
||||
riscv_program_csrrw(&program32, GDB_REGNO_S0, GDB_REGNO_S0, GDB_REGNO_DSCRATCH);
|
||||
riscv_program_fence(&program32);
|
||||
riscv_program_exec(&program32, target);
|
||||
|
||||
riscv_addr_t progbuf_addr = dmi_read(target, DMI_PROGBUF0) - 4;
|
||||
if (get_field(dmi_read(target, DMI_ABSTRACTCS), DMI_ABSTRACTCS_CMDERR) != 0) {
|
||||
LOG_ERROR("Unable to find the address of the program buffer on hart %d", i);
|
||||
r->xlen[i] = -1;
|
||||
continue;
|
||||
}
|
||||
r->debug_buffer_addr[i] = progbuf_addr;
|
||||
|
||||
/* Check to see if the core can execute 64 bit instructions.
|
||||
* In order to make this work we first need to */
|
||||
int offset = (progbuf_addr % 8 == 0) ? -4 : 0;
|
||||
|
||||
/* This program uses a temporary register. If the core can not
|
||||
* execute 64 bit instruction, the original value of temporary
|
||||
* register (s0) will not be restored due to an exception.
|
||||
* So we have to save it and restore manually in that case.
|
||||
* If the core can execute 64 bit instruction, the saved value
|
||||
* is wrong, because it was read with 32 bit lw instruction,
|
||||
* but the value of s0 will be restored by the reverse swap
|
||||
* of s0 and dscratch registers. */
|
||||
uint64_t s0 = riscv_get_register(target, GDB_REGNO_S0);
|
||||
|
||||
struct riscv_program program64;
|
||||
riscv_program_init(&program64, target);
|
||||
riscv_program_csrrw(&program64, GDB_REGNO_S0, GDB_REGNO_S0, GDB_REGNO_DSCRATCH);
|
||||
riscv_program_insert(&program64, auipc(GDB_REGNO_S0));
|
||||
riscv_program_insert(&program64, sd(GDB_REGNO_S0, GDB_REGNO_S0, offset));
|
||||
riscv_program_csrrw(&program64, GDB_REGNO_S0, GDB_REGNO_S0, GDB_REGNO_DSCRATCH);
|
||||
riscv_program_fence(&program64);
|
||||
int result = riscv_program_exec(&program64, target);
|
||||
// >>> r->xlen[i] = 32;
|
||||
|
||||
uint64_t value;
|
||||
int result = register_read_abstract(target, &value, GDB_REGNO_S0, 64);
|
||||
if (result == ERROR_OK) {
|
||||
r->debug_buffer_addr[i] =
|
||||
(dmi_read(target, DMI_PROGBUF0 + (8 + offset) / 4) << 32)
|
||||
+ dmi_read(target, DMI_PROGBUF0 + (4 + offset) / 4)
|
||||
- 4;
|
||||
r->xlen[i] = 64;
|
||||
} else {
|
||||
riscv_set_register(target, GDB_REGNO_S0, s0);
|
||||
r->xlen[i] = 32;
|
||||
}
|
||||
|
||||
/* Display this as early as possible to help people who are using
|
||||
* really slow simulators. */
|
||||
LOG_DEBUG(" hart %d: XLEN=%d, program buffer at 0x%" PRIx64, i,
|
||||
r->xlen[i], r->debug_buffer_addr[i]);
|
||||
|
||||
if (riscv_program_gah(&program64, r->debug_buffer_addr[i])) {
|
||||
LOG_ERROR("This implementation will not work with hart %d with debug_buffer_addr of 0x%lx", i,
|
||||
(long)r->debug_buffer_addr[i]);
|
||||
abort();
|
||||
}
|
||||
|
||||
/* Check to see if we can use the data words as an extended
|
||||
* program buffer or not. */
|
||||
if (r->debug_buffer_addr[i] + (4 * r->debug_buffer_size[i]) == riscv013_data_addr(target)) {
|
||||
r->debug_buffer_size[i] += riscv013_data_size(target);
|
||||
LOG_DEBUG("extending the debug buffer using data words, total size %d", r->debug_buffer_size[i]);
|
||||
}
|
||||
LOG_DEBUG(" hart %d: XLEN=%d", i, r->xlen[i]);
|
||||
}
|
||||
|
||||
/* Then we check the number of triggers availiable to each hart. */
|
||||
|
@ -1172,8 +1136,7 @@ static int examine(struct target *target)
|
|||
riscv_count_harts(target));
|
||||
for (int i = 0; i < riscv_count_harts(target); ++i) {
|
||||
if (riscv_hart_enabled(target, i)) {
|
||||
LOG_INFO(" hart %d: XLEN=%d, program buffer at 0x%" PRIx64
|
||||
", %d triggers", i, r->xlen[i], r->debug_buffer_addr[i],
|
||||
LOG_INFO(" hart %d: XLEN=%d, %d triggers", i, r->xlen[i],
|
||||
r->trigger_count[i]);
|
||||
} else {
|
||||
LOG_INFO(" hart %d: currently disabled", i);
|
||||
|
@ -1296,6 +1259,7 @@ static int deassert_reset(struct target *target)
|
|||
return ERROR_OK;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void write_to_buf(uint8_t *buffer, uint64_t value, unsigned size)
|
||||
{
|
||||
switch (size) {
|
||||
|
@ -1316,6 +1280,7 @@ static void write_to_buf(uint8_t *buffer, uint64_t value, unsigned size)
|
|||
assert(false);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Read the requested memory, taking care to execute every read exactly once,
|
||||
|
@ -1324,7 +1289,7 @@ static void write_to_buf(uint8_t *buffer, uint64_t value, unsigned size)
|
|||
static int read_memory(struct target *target, target_addr_t address,
|
||||
uint32_t size, uint32_t count, uint8_t *buffer)
|
||||
{
|
||||
RISCV013_INFO(info);
|
||||
//RISCV013_INFO(info);
|
||||
|
||||
LOG_DEBUG("reading %d words of %d bytes from 0x%" TARGET_PRIxADDR, count,
|
||||
size, address);
|
||||
|
@ -1342,6 +1307,8 @@ static int read_memory(struct target *target, target_addr_t address,
|
|||
|
||||
struct riscv_program program;
|
||||
riscv_program_init(&program, target);
|
||||
assert(0);
|
||||
#if 0
|
||||
riscv_addr_t r_data = riscv_program_alloc_w(&program);
|
||||
riscv_addr_t r_addr = riscv_program_alloc_x(&program);
|
||||
riscv_program_fence(&program);
|
||||
|
@ -1496,6 +1463,7 @@ static int read_memory(struct target *target, target_addr_t address,
|
|||
riscv_addr_t addr = cur_addr - size;
|
||||
write_to_buf(buffer + addr - address, value, size);
|
||||
LOG_DEBUG("M[0x%" TARGET_PRIxADDR "] reads 0x%08x", addr, value);
|
||||
#endif
|
||||
|
||||
riscv_set_register(target, GDB_REGNO_S0, s0);
|
||||
riscv_set_register(target, GDB_REGNO_S1, s1);
|
||||
|
@ -1505,7 +1473,7 @@ static int read_memory(struct target *target, target_addr_t address,
|
|||
static int write_memory(struct target *target, target_addr_t address,
|
||||
uint32_t size, uint32_t count, const uint8_t *buffer)
|
||||
{
|
||||
RISCV013_INFO(info);
|
||||
//RISCV013_INFO(info);
|
||||
|
||||
LOG_DEBUG("writing %d words of %d bytes to 0x%08lx", count, size, (long)address);
|
||||
|
||||
|
@ -1522,6 +1490,8 @@ static int write_memory(struct target *target, target_addr_t address,
|
|||
|
||||
struct riscv_program program;
|
||||
riscv_program_init(&program, target);
|
||||
assert(0);
|
||||
#if 0
|
||||
riscv_addr_t r_data = riscv_program_alloc_w(&program);
|
||||
riscv_addr_t r_addr = riscv_program_alloc_x(&program);
|
||||
riscv_program_fence(&program);
|
||||
|
@ -1682,6 +1652,7 @@ static int write_memory(struct target *target, target_addr_t address,
|
|||
}
|
||||
|
||||
riscv013_set_autoexec(target, d_data, 0);
|
||||
#endif
|
||||
riscv_set_register(target, GDB_REGNO_S0, s0);
|
||||
riscv_set_register(target, GDB_REGNO_S1, s1);
|
||||
return ERROR_OK;
|
||||
|
@ -1992,13 +1963,16 @@ static void riscv013_step_or_resume_current_hart(struct target *target, bool ste
|
|||
abort();
|
||||
}
|
||||
|
||||
#if 0
|
||||
riscv_addr_t riscv013_progbuf_addr(struct target *target)
|
||||
{
|
||||
RISCV013_INFO(info);
|
||||
assert(info->progbuf_addr != -1);
|
||||
return info->progbuf_addr;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
riscv_addr_t riscv013_data_size(struct target *target)
|
||||
{
|
||||
RISCV013_INFO(info);
|
||||
|
@ -2008,7 +1982,9 @@ riscv_addr_t riscv013_data_size(struct target *target)
|
|||
}
|
||||
return info->data_size;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
riscv_addr_t riscv013_data_addr(struct target *target)
|
||||
{
|
||||
RISCV013_INFO(info);
|
||||
|
@ -2018,7 +1994,9 @@ riscv_addr_t riscv013_data_addr(struct target *target)
|
|||
}
|
||||
return info->data_addr;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
void riscv013_set_autoexec(struct target *target, unsigned index, bool enabled)
|
||||
{
|
||||
RISCV013_INFO(info);
|
||||
|
@ -2040,7 +2018,9 @@ void riscv013_set_autoexec(struct target *target, unsigned index, bool enabled)
|
|||
dmi_write(target, DMI_ABSTRACTAUTO, aa);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
int riscv013_debug_buffer_register(struct target *target, riscv_addr_t addr)
|
||||
{
|
||||
if (addr >= riscv013_data_addr(target))
|
||||
|
@ -2069,3 +2049,4 @@ void riscv013_clear_abstract_error(struct target *target)
|
|||
// Clear the error status.
|
||||
dmi_write(target, DMI_ABSTRACTCS, abstractcs & DMI_ABSTRACTCS_CMDERR);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1235,7 +1235,6 @@ void riscv_info_init(struct target *target, riscv_info_t *r)
|
|||
|
||||
for (size_t h = 0; h < RISCV_MAX_HARTS; ++h) {
|
||||
r->xlen[h] = -1;
|
||||
r->debug_buffer_addr[h] = -1;
|
||||
|
||||
for (size_t e = 0; e < RISCV_MAX_REGISTERS; ++e)
|
||||
r->valid_saved_registers[h][e] = false;
|
||||
|
@ -1483,14 +1482,6 @@ size_t riscv_debug_buffer_size(struct target *target)
|
|||
return r->debug_buffer_size[riscv_current_hartid(target)];
|
||||
}
|
||||
|
||||
riscv_addr_t riscv_debug_buffer_addr(struct target *target)
|
||||
{
|
||||
RISCV_INFO(r);
|
||||
riscv_addr_t out = r->debug_buffer_addr[riscv_current_hartid(target)];
|
||||
assert((out & 3) == 0);
|
||||
return out;
|
||||
}
|
||||
|
||||
int riscv_debug_buffer_enter(struct target *target, struct riscv_program *program)
|
||||
{
|
||||
RISCV_INFO(r);
|
||||
|
|
|
@ -72,9 +72,6 @@ typedef struct {
|
|||
* target controls, while otherwise only a single hart is controlled. */
|
||||
int trigger_unique_id[RISCV_MAX_HWBPS];
|
||||
|
||||
/* The address of the debug RAM buffer. */
|
||||
riscv_addr_t debug_buffer_addr[RISCV_MAX_HARTS];
|
||||
|
||||
/* The number of entries in the debug buffer. */
|
||||
int debug_buffer_size[RISCV_MAX_HARTS];
|
||||
|
||||
|
@ -213,7 +210,6 @@ int riscv_count_triggers_of_hart(struct target *target, int hartid);
|
|||
/* These helper functions let the generic program interface get target-specific
|
||||
* information. */
|
||||
size_t riscv_debug_buffer_size(struct target *target);
|
||||
riscv_addr_t riscv_debug_buffer_addr(struct target *target);
|
||||
|
||||
int riscv_debug_buffer_enter(struct target *target, struct riscv_program *program);
|
||||
int riscv_debug_buffer_leave(struct target *target, struct riscv_program *program);
|
||||
|
|
Loading…
Reference in New Issue