From ea6836c5f65cb757a2675cd8e961bcd6e0bdd965 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Mon, 23 May 2016 16:27:43 -0700 Subject: [PATCH] WIP, blind coding. --- src/target/riscv/encoding.h | 40 +++++++-------- src/target/riscv/opcodes.h | 2 +- src/target/riscv/riscv.c | 97 +++++++++++++++++++++++++++++++++---- src/target/target_type.h | 1 + 4 files changed, 110 insertions(+), 30 deletions(-) diff --git a/src/target/riscv/encoding.h b/src/target/riscv/encoding.h index 9f0929f15..b290604c5 100644 --- a/src/target/riscv/encoding.h +++ b/src/target/riscv/encoding.h @@ -33,28 +33,28 @@ #define SSTATUS32_SD 0x80000000 #define SSTATUS64_SD 0x8000000000000000 -#define DCSR_XDEBUGVER (3<<29) -#define DCSR_HWBPCOUNT (0xfff<<17) -#define DCSR_PRV (3<<14) -#define DCSR_NDRESET (1<<13) -#define DCSR_FULLRESET (1<<12) -#define DCSR_STEP (1<<11) -#define DCSR_DEBUGINT (1<<10) -#define DCSR_STOPCYCLE (1<<9) -#define DCSR_STOPTIME (1<<8) -#define DCSR_EBREAKM (1<<7) -#define DCSR_EBREAKH (1<<6) -#define DCSR_EBREAKS (1<<5) -#define DCSR_EBREAKU (1<<4) +#define DCSR_XDEBUGVER (3<<30) +#define DCSR_NDRESET (1<<29) +#define DCSR_FULLRESET (1<<28) +#define DCSR_HWBPCOUNT (0xfff<<16) +#define DCSR_EBREAKM (1<<15) +#define DCSR_EBREAKH (1<<14) +#define DCSR_EBREAKS (1<<13) +#define DCSR_EBREAKU (1<<12) +#define DCSR_STOPCYCLE (1<<10) +#define DCSR_STOPTIME (1<<9) +#define DCSR_CAUSE (7<<6) +#define DCSR_DEBUGINT (1<<5) #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_SWBP 1 -#define DCSR_CAUSE_HWBP 2 -#define DCSR_CAUSE_DEBUGINT 3 -#define DCSR_CAUSE_STEP 4 -#define DCSR_CAUSE_HALT 5 +#define DCSR_CAUSE_NONE (0<<6) +#define DCSR_CAUSE_SWBP (1<<6) +#define DCSR_CAUSE_HWBP (2<<6) +#define DCSR_CAUSE_DEBUGINT (3<<6) +#define DCSR_CAUSE_STEP (4<<6) +#define DCSR_CAUSE_HALT (5<<6) #define MIP_SSIP (1 << IRQ_S_SOFT) #define MIP_HSIP (1 << IRQ_H_SOFT) diff --git a/src/target/riscv/opcodes.h b/src/target/riscv/opcodes.h index 6dd0e1e18..a1d9f8f1c 100644 --- a/src/target/riscv/opcodes.h +++ b/src/target/riscv/opcodes.h @@ -52,13 +52,13 @@ static uint32_t srli(unsigned int dest, unsigned int src, uint8_t shamt) MATCH_SRLI; } -/* static uint32_t csrci(unsigned int csr, uint16_t imm) { return (csr << 20) | (bits(imm, 4, 0) << 15) | MATCH_CSRRCI; } +/* static uint32_t csrr(unsigned int rd, unsigned int csr) { return (csr << 20) | (rd << 7) | MATCH_CSRRS; } diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index 64e44e0c9..a4cc78e07 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -92,8 +92,13 @@ typedef struct { * confident that the value we have matches the one in actual Debug * RAM. */ uint64_t dram_valid; + uint32_t dcsr; } riscv_info_t; +/*** Necessary prototypes. ***/ + +static int riscv_poll(struct target *target); + /*** Utility functions. ***/ 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); } +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. ***/ static int riscv_init_target(struct command_context *cmd_ctx, @@ -301,20 +351,15 @@ static int riscv_examine(struct target *target) return ERROR_FAIL; } - // TODO: 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 - + // Figure out XLEN. 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); + // 0x00000001 0x00000001:ffffffff 0x00000001:ffffffff:ffffffff:ffffffff dram_write32(target, 2, sw(S1, ZERO, DEBUG_RAM_START), 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_write_jump(target, 5, true); // Check that we can actually read/write dram. 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, 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); return ERROR_OK; @@ -365,6 +429,19 @@ static int riscv_halt(struct target *target) 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) { // TODO @@ -388,6 +465,8 @@ struct target_type riscv_target = { .poll = riscv_poll, .halt = riscv_halt, + .resume = riscv_resume, + .step = riscv_step, .assert_reset = riscv_assert_reset, .deassert_reset = riscv_deassert_reset, diff --git a/src/target/target_type.h b/src/target/target_type.h index eaa8a71cc..95c0fef11 100644 --- a/src/target/target_type.h +++ b/src/target/target_type.h @@ -53,6 +53,7 @@ struct target_type { /* halt will log a warning, but return ERROR_OK if the target is already halted. */ int (*halt)(struct target *target); + /* See target.c target_resume() for documentation. */ int (*resume)(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution); int (*step)(struct target *target, int current, uint32_t address,