WIP, blind coding.
parent
413ab49dfd
commit
ea6836c5f6
|
@ -33,28 +33,28 @@
|
||||||
#define SSTATUS32_SD 0x80000000
|
#define SSTATUS32_SD 0x80000000
|
||||||
#define SSTATUS64_SD 0x8000000000000000
|
#define SSTATUS64_SD 0x8000000000000000
|
||||||
|
|
||||||
#define DCSR_XDEBUGVER (3<<29)
|
#define DCSR_XDEBUGVER (3<<30)
|
||||||
#define DCSR_HWBPCOUNT (0xfff<<17)
|
#define DCSR_NDRESET (1<<29)
|
||||||
#define DCSR_PRV (3<<14)
|
#define DCSR_FULLRESET (1<<28)
|
||||||
#define DCSR_NDRESET (1<<13)
|
#define DCSR_HWBPCOUNT (0xfff<<16)
|
||||||
#define DCSR_FULLRESET (1<<12)
|
#define DCSR_EBREAKM (1<<15)
|
||||||
#define DCSR_STEP (1<<11)
|
#define DCSR_EBREAKH (1<<14)
|
||||||
#define DCSR_DEBUGINT (1<<10)
|
#define DCSR_EBREAKS (1<<13)
|
||||||
#define DCSR_STOPCYCLE (1<<9)
|
#define DCSR_EBREAKU (1<<12)
|
||||||
#define DCSR_STOPTIME (1<<8)
|
#define DCSR_STOPCYCLE (1<<10)
|
||||||
#define DCSR_EBREAKM (1<<7)
|
#define DCSR_STOPTIME (1<<9)
|
||||||
#define DCSR_EBREAKH (1<<6)
|
#define DCSR_CAUSE (7<<6)
|
||||||
#define DCSR_EBREAKS (1<<5)
|
#define DCSR_DEBUGINT (1<<5)
|
||||||
#define DCSR_EBREAKU (1<<4)
|
|
||||||
#define DCSR_HALT (1<<3)
|
#define DCSR_HALT (1<<3)
|
||||||
#define DCSR_CAUSE 7
|
#define DCSR_STEP (1<<2)
|
||||||
|
#define DCSR_PRV (3<<0)
|
||||||
|
|
||||||
#define DCSR_CAUSE_NONE 0
|
#define DCSR_CAUSE_NONE (0<<6)
|
||||||
#define DCSR_CAUSE_SWBP 1
|
#define DCSR_CAUSE_SWBP (1<<6)
|
||||||
#define DCSR_CAUSE_HWBP 2
|
#define DCSR_CAUSE_HWBP (2<<6)
|
||||||
#define DCSR_CAUSE_DEBUGINT 3
|
#define DCSR_CAUSE_DEBUGINT (3<<6)
|
||||||
#define DCSR_CAUSE_STEP 4
|
#define DCSR_CAUSE_STEP (4<<6)
|
||||||
#define DCSR_CAUSE_HALT 5
|
#define DCSR_CAUSE_HALT (5<<6)
|
||||||
|
|
||||||
#define MIP_SSIP (1 << IRQ_S_SOFT)
|
#define MIP_SSIP (1 << IRQ_S_SOFT)
|
||||||
#define MIP_HSIP (1 << IRQ_H_SOFT)
|
#define MIP_HSIP (1 << IRQ_H_SOFT)
|
||||||
|
|
|
@ -52,13 +52,13 @@ static uint32_t srli(unsigned int dest, unsigned int src, uint8_t shamt)
|
||||||
MATCH_SRLI;
|
MATCH_SRLI;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
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 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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,8 +92,13 @@ typedef struct {
|
||||||
* confident that the value we have matches the one in actual Debug
|
* confident that the value we have matches the one in actual Debug
|
||||||
* RAM. */
|
* RAM. */
|
||||||
uint64_t dram_valid;
|
uint64_t dram_valid;
|
||||||
|
uint32_t dcsr;
|
||||||
} riscv_info_t;
|
} riscv_info_t;
|
||||||
|
|
||||||
|
/*** Necessary prototypes. ***/
|
||||||
|
|
||||||
|
static int riscv_poll(struct target *target);
|
||||||
|
|
||||||
/*** Utility functions. ***/
|
/*** Utility functions. ***/
|
||||||
|
|
||||||
static uint8_t ir_dtminfo[1] = {DTMINFO};
|
static uint8_t ir_dtminfo[1] = {DTMINFO};
|
||||||
|
@ -246,6 +251,51 @@ static void dram_write_jump(struct target *target, unsigned int index, bool set_
|
||||||
set_interrupt);
|
set_interrupt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int wait_until_halted(struct target *target)
|
||||||
|
{
|
||||||
|
do {
|
||||||
|
int result = riscv_poll(target);
|
||||||
|
if (result != ERROR_OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
} while (target->state != TARGET_HALTED);
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int resume(struct target *target, int current, uint32_t address,
|
||||||
|
int handle_breakpoints, int debug_execution, bool step)
|
||||||
|
{
|
||||||
|
riscv_info_t *info = (riscv_info_t *) target->arch_info;
|
||||||
|
if (!current) {
|
||||||
|
if (info->xlen > 32) {
|
||||||
|
LOG_WARNING("Asked to resume at 32-bit PC on %d-bit target.",
|
||||||
|
info->xlen);
|
||||||
|
}
|
||||||
|
LOG_ERROR("TODO: current is false");
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handle_breakpoints) {
|
||||||
|
LOG_ERROR("TODO: handle_breakpoints is true");
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug_execution) {
|
||||||
|
LOG_ERROR("TODO: debug_execution is true");
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
dram_write32(target, 0, csrsi(CSR_DCSR, DCSR_HALT), false);
|
||||||
|
if (step) {
|
||||||
|
dram_write32(target, 1, csrsi(CSR_DCSR, DCSR_STEP), false);
|
||||||
|
} else {
|
||||||
|
dram_write32(target, 1, csrci(CSR_DCSR, DCSR_STEP), false);
|
||||||
|
}
|
||||||
|
dram_write_jump(target, 2, true);
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/*** OpenOCD target functions. ***/
|
/*** OpenOCD target functions. ***/
|
||||||
|
|
||||||
static int riscv_init_target(struct command_context *cmd_ctx,
|
static int riscv_init_target(struct command_context *cmd_ctx,
|
||||||
|
@ -301,20 +351,15 @@ static int riscv_examine(struct target *target)
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Figure out XLEN.
|
// Figure out XLEN.
|
||||||
// xori s1, zero, -1 0xffffffff 0xffffffff:ffffffff 0xffffffff:ffffffff:ffffffff:ffffffff
|
|
||||||
// srli s1, s1, 31 0x00000001 0x00000001:ffffffff 0x00000001:ffffffff:ffffffff:ffffffff
|
|
||||||
// sw s1, debug_ram
|
|
||||||
// srli s1, s1, 31 0x00000000 0x00000000:00000003 0x00000000:00000003:ffffffff:ffffffff
|
|
||||||
// sw s1, debug_ram + 4
|
|
||||||
// jump back
|
|
||||||
|
|
||||||
dram_write32(target, 0, xori(S1, ZERO, -1), false);
|
dram_write32(target, 0, xori(S1, ZERO, -1), false);
|
||||||
|
// 0xffffffff 0xffffffff:ffffffff 0xffffffff:ffffffff:ffffffff:ffffffff
|
||||||
dram_write32(target, 1, srli(S1, S1, 31), false);
|
dram_write32(target, 1, srli(S1, S1, 31), false);
|
||||||
|
// 0x00000001 0x00000001:ffffffff 0x00000001:ffffffff:ffffffff:ffffffff
|
||||||
dram_write32(target, 2, sw(S1, ZERO, DEBUG_RAM_START), false);
|
dram_write32(target, 2, sw(S1, ZERO, DEBUG_RAM_START), false);
|
||||||
dram_write32(target, 3, srli(S1, S1, 31), false);
|
dram_write32(target, 3, srli(S1, S1, 31), false);
|
||||||
|
// 0x00000000 0x00000000:00000003 0x00000000:00000003:ffffffff:ffffffff
|
||||||
dram_write32(target, 4, sw(S1, ZERO, DEBUG_RAM_START + 4), false);
|
dram_write32(target, 4, sw(S1, ZERO, DEBUG_RAM_START + 4), false);
|
||||||
dram_write_jump(target, 5, true);
|
|
||||||
|
|
||||||
// Check that we can actually read/write dram.
|
// Check that we can actually read/write dram.
|
||||||
dram_check32(target, 0, xori(S1, ZERO, -1));
|
dram_check32(target, 0, xori(S1, ZERO, -1));
|
||||||
|
@ -323,6 +368,25 @@ static int riscv_examine(struct target *target)
|
||||||
dram_check32(target, 3, srli(S1, S1, 31));
|
dram_check32(target, 3, srli(S1, S1, 31));
|
||||||
dram_check32(target, 4, sw(S1, ZERO, DEBUG_RAM_START + 4));
|
dram_check32(target, 4, sw(S1, ZERO, DEBUG_RAM_START + 4));
|
||||||
|
|
||||||
|
// Execute.
|
||||||
|
dram_write_jump(target, 5, true);
|
||||||
|
|
||||||
|
wait_until_halted(target);
|
||||||
|
|
||||||
|
uint32_t word0 = dram_read32(target, 0, false);
|
||||||
|
uint32_t word1 = dram_read32(target, 1, false);
|
||||||
|
if (word0 == 1 && word1 == 0) {
|
||||||
|
info->xlen = 32;
|
||||||
|
} else if (word0 == 0xffffffff && word1 == 3) {
|
||||||
|
info->xlen = 64;
|
||||||
|
} else if (word0 == 0xffffffff && word1 == 0xffffffff) {
|
||||||
|
info->xlen = 128;
|
||||||
|
} else {
|
||||||
|
LOG_ERROR("Failed to discover xlen; word0=0x%x, word1=0x%x",
|
||||||
|
word0, word1);
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
target_set_examined(target);
|
target_set_examined(target);
|
||||||
|
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
|
@ -365,6 +429,19 @@ static int riscv_halt(struct target *target)
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int riscv_resume(struct target *target, int current, uint32_t address,
|
||||||
|
int handle_breakpoints, int debug_execution)
|
||||||
|
{
|
||||||
|
return resume(target, current, address, handle_breakpoints,
|
||||||
|
debug_execution, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int riscv_step(struct target *target, int current, uint32_t address,
|
||||||
|
int handle_breakpoints)
|
||||||
|
{
|
||||||
|
return resume(target, current, address, handle_breakpoints, 0, true);
|
||||||
|
}
|
||||||
|
|
||||||
static int riscv_assert_reset(struct target *target)
|
static int riscv_assert_reset(struct target *target)
|
||||||
{
|
{
|
||||||
// TODO
|
// TODO
|
||||||
|
@ -388,6 +465,8 @@ struct target_type riscv_target = {
|
||||||
.poll = riscv_poll,
|
.poll = riscv_poll,
|
||||||
|
|
||||||
.halt = riscv_halt,
|
.halt = riscv_halt,
|
||||||
|
.resume = riscv_resume,
|
||||||
|
.step = riscv_step,
|
||||||
|
|
||||||
.assert_reset = riscv_assert_reset,
|
.assert_reset = riscv_assert_reset,
|
||||||
.deassert_reset = riscv_deassert_reset,
|
.deassert_reset = riscv_deassert_reset,
|
||||||
|
|
|
@ -53,6 +53,7 @@ struct target_type {
|
||||||
|
|
||||||
/* halt will log a warning, but return ERROR_OK if the target is already halted. */
|
/* halt will log a warning, but return ERROR_OK if the target is already halted. */
|
||||||
int (*halt)(struct target *target);
|
int (*halt)(struct target *target);
|
||||||
|
/* See target.c target_resume() for documentation. */
|
||||||
int (*resume)(struct target *target, int current, uint32_t address,
|
int (*resume)(struct target *target, int current, uint32_t address,
|
||||||
int handle_breakpoints, int debug_execution);
|
int handle_breakpoints, int debug_execution);
|
||||||
int (*step)(struct target *target, int current, uint32_t address,
|
int (*step)(struct target *target, int current, uint32_t address,
|
||||||
|
|
Loading…
Reference in New Issue