diff --git a/src/target/riscv/encoding.h b/src/target/riscv/encoding.h index b290604c5..032626ea9 100644 --- a/src/target/riscv/encoding.h +++ b/src/target/riscv/encoding.h @@ -33,7 +33,7 @@ #define SSTATUS32_SD 0x80000000 #define SSTATUS64_SD 0x8000000000000000 -#define DCSR_XDEBUGVER (3<<30) +#define DCSR_XDEBUGVER (3U<<30) #define DCSR_NDRESET (1<<29) #define DCSR_FULLRESET (1<<28) #define DCSR_HWBPCOUNT (0xfff<<16) @@ -49,12 +49,12 @@ #define DCSR_STEP (1<<2) #define DCSR_PRV (3<<0) -#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 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 MIP_SSIP (1 << IRQ_S_SOFT) #define MIP_HSIP (1 << IRQ_H_SOFT) @@ -62,6 +62,9 @@ #define MIP_STIP (1 << IRQ_S_TIMER) #define MIP_HTIP (1 << IRQ_H_TIMER) #define MIP_MTIP (1 << IRQ_M_TIMER) +#define MIP_SEIP (1 << IRQ_S_EXT) +#define MIP_HEIP (1 << IRQ_H_EXT) +#define MIP_MEIP (1 << IRQ_M_EXT) #define SIP_SSIP MIP_SSIP #define SIP_STIP MIP_STIP @@ -84,9 +87,9 @@ #define IRQ_S_TIMER 5 #define IRQ_H_TIMER 6 #define IRQ_M_TIMER 7 -#define IRQ_S_DEV 9 -#define IRQ_H_DEV 10 -#define IRQ_M_DEV 11 +#define IRQ_S_EXT 9 +#define IRQ_H_EXT 10 +#define IRQ_M_EXT 11 #define IRQ_COP 12 #define IRQ_HOST 13 @@ -383,7 +386,7 @@ #define MASK_HRET 0xffffffff #define MATCH_MRET 0x30200073 #define MASK_MRET 0xffffffff -#define MATCH_DRET 0x79200073 +#define MATCH_DRET 0x7b200073 #define MASK_DRET 0xffffffff #define MATCH_SFENCE_VM 0x10400073 #define MASK_SFENCE_VM 0xfff07fff @@ -686,7 +689,6 @@ #define CSR_MCAUSE 0x342 #define CSR_MBADADDR 0x343 #define CSR_MIP 0x344 -#define CSR_MIPI 0x345 #define CSR_MUCOUNTEREN 0x310 #define CSR_MSCOUNTEREN 0x311 #define CSR_MUCYCLE_DELTA 0x700 @@ -695,9 +697,9 @@ #define CSR_MSCYCLE_DELTA 0x704 #define CSR_MSTIME_DELTA 0x705 #define CSR_MSINSTRET_DELTA 0x706 -#define CSR_DCSR 0x790 -#define CSR_DPC 0x791 -#define CSR_DSCRATCH 0x792 +#define CSR_DCSR 0x7b0 +#define CSR_DPC 0x7b1 +#define CSR_DSCRATCH 0x7b2 #define CSR_MCYCLE 0xf00 #define CSR_MTIME 0xf01 #define CSR_MINSTRET 0xf02 @@ -706,8 +708,6 @@ #define CSR_MARCHID 0xf12 #define CSR_MIMPID 0xf13 #define CSR_MHARTID 0xf14 -#define CSR_MTOHOST 0x7c0 -#define CSR_MFROMHOST 0x7c1 #define CSR_MRESET 0x7c2 #define CSR_CYCLEH 0xc80 #define CSR_TIMEH 0xc81 @@ -995,7 +995,6 @@ DECLARE_CSR(mepc, CSR_MEPC) DECLARE_CSR(mcause, CSR_MCAUSE) DECLARE_CSR(mbadaddr, CSR_MBADADDR) DECLARE_CSR(mip, CSR_MIP) -DECLARE_CSR(mipi, CSR_MIPI) DECLARE_CSR(mucounteren, CSR_MUCOUNTEREN) DECLARE_CSR(mscounteren, CSR_MSCOUNTEREN) DECLARE_CSR(mucycle_delta, CSR_MUCYCLE_DELTA) @@ -1015,8 +1014,6 @@ DECLARE_CSR(mvendorid, CSR_MVENDORID) DECLARE_CSR(marchid, CSR_MARCHID) DECLARE_CSR(mimpid, CSR_MIMPID) DECLARE_CSR(mhartid, CSR_MHARTID) -DECLARE_CSR(mtohost, CSR_MTOHOST) -DECLARE_CSR(mfromhost, CSR_MFROMHOST) DECLARE_CSR(mreset, CSR_MRESET) DECLARE_CSR(cycleh, CSR_CYCLEH) DECLARE_CSR(timeh, CSR_TIMEH) diff --git a/src/target/riscv/opcodes.h b/src/target/riscv/opcodes.h index 4322808b8..1e46b80f4 100644 --- a/src/target/riscv/opcodes.h +++ b/src/target/riscv/opcodes.h @@ -117,6 +117,15 @@ static uint32_t csrr(unsigned int rd, unsigned int csr) { return (csr << 20) | (rd << 7) | MATCH_CSRRS; } +static uint32_t fsw(unsigned int src, unsigned int base, uint16_t offset) +{ + return (bits(offset, 11, 5) << 25) | + (bits(src, 4, 0) << 20) | + (base << 15) | + (bits(offset, 4, 0) << 7) | + MATCH_FSW; +} + /* static uint32_t li(unsigned int dest, uint16_t imm) { diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index a4bf25af5..089e99c5d 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -294,14 +294,18 @@ static int dram_check32(struct target *target, unsigned int index, static bits_t read_bits(struct target *target) { riscv_info_t *info = (riscv_info_t *) target->arch_info; + static int next_address = 0; uint64_t value; if (info->dbus_address < 0x10 || info->dbus_address == DMCONTROL) { - value = dbus_read(target, info->dbus_address, 0); + value = dbus_read(target, info->dbus_address, next_address); } else { - value = dbus_read(target, 0, 0); + value = dbus_read(target, 0, next_address); } + // Cycle through addresses, so we have more debug info. + next_address = (next_address + 1) % (info->dramsize + 1); + bits_t result = { .haltnot = get_field(value, DMCONTROL_HALTNOT), .interrupt = get_field(value, DMCONTROL_INTERRUPT) @@ -415,11 +419,22 @@ static int register_get(struct reg *reg) { struct target *target = (struct target *) reg->arch_info; - if (reg->number == REG_PC) { + if (reg->number <= REG_XPR31) { + dram_write32(target, 0, sw(reg->number - REG_XPR0, ZERO, DEBUG_RAM_START), false); + dram_write_jump(target, 1, true); + } else if (reg->number == REG_PC) { dram_write32(target, 0, csrr(S0, CSR_DPC), false); dram_write32(target, 1, sw(S0, ZERO, DEBUG_RAM_START), false); dram_write_jump(target, 2, true); + } else if (reg->number >= REG_FPR0 && reg->number <= REG_FPR31) { + dram_write32(target, 0, fsw(reg->number - REG_FPR0, 0, DEBUG_RAM_START), false); + dram_write_jump(target, 1, true); + } else if (reg->number >= REG_CSR0 && reg->number <= REG_CSR4095) { + dram_write32(target, 0, csrr(S0, reg->number - REG_CSR0), false); + dram_write32(target, 1, sw(S0, ZERO, DEBUG_RAM_START), false); + dram_write_jump(target, 2, true); } else { + LOG_ERROR("Don't know how to read register %d (%s)", reg->number, reg->name); return ERROR_FAIL; } @@ -428,7 +443,9 @@ static int register_get(struct reg *reg) return ERROR_FAIL; } - buf_set_u32(reg->value, 0, 32, dram_read32(target, 0)); + uint32_t value = dram_read32(target, 0); + LOG_DEBUG("%s=0x%x", reg->name, value); + buf_set_u32(reg->value, 0, 32, value); return ERROR_OK; } @@ -664,10 +681,14 @@ static int riscv_examine(struct target *target) return ERROR_FAIL; } - // TODO: Doesn't work with this extra nop. - dram_write32(target, 5, nop(), false); // Execute. +#if 1 + // TODO: Doesn't work without this extra nop. + dram_write32(target, 5, nop(), false); dram_write_jump(target, 6, true); +#else + dram_write_jump(target, 5, true); +#endif if (wait_for_debugint_clear(target) != ERROR_OK) { LOG_ERROR("Debug interrupt didn't clear.");