Merge pull request #131 from riscv/small_progbuf

Support program buffers that are just 2 instructions large
macbuild
Tim Newsome 2017-12-11 12:52:31 -08:00 committed by GitHub
commit e50ee46a6f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 780 additions and 1018 deletions

View File

@ -49,13 +49,12 @@ void riscv_batch_run(struct riscv_batch *batch)
return; return;
} }
keep_alive(); keep_alive();
LOG_DEBUG("running a batch of %ld scans", (long)batch->used_scans); LOG_DEBUG("running a batch of %ld scans", (long)batch->used_scans);
riscv_batch_add_nop(batch); riscv_batch_add_nop(batch);
for (size_t i = 0; i < batch->used_scans; ++i) { for (size_t i = 0; i < batch->used_scans; ++i) {
dump_field(batch->fields + i);
jtag_add_dr_scan(batch->target->tap, 1, batch->fields + i, TAP_IDLE); jtag_add_dr_scan(batch->target->tap, 1, batch->fields + i, TAP_IDLE);
if (batch->idle_count > 0) if (batch->idle_count > 0)
jtag_add_runtest(batch->idle_count, TAP_IDLE); jtag_add_runtest(batch->idle_count, TAP_IDLE);

View File

@ -173,12 +173,6 @@
#define CSR_DCSR_EBREAKM_LENGTH 1 #define CSR_DCSR_EBREAKM_LENGTH 1
#define CSR_DCSR_EBREAKM (0x1U << CSR_DCSR_EBREAKM_OFFSET) #define CSR_DCSR_EBREAKM (0x1U << CSR_DCSR_EBREAKM_OFFSET)
/* /*
* When 1, {\tt ebreak} instructions in Hypervisor Mode enter Debug Mode.
*/
#define CSR_DCSR_EBREAKH_OFFSET 14
#define CSR_DCSR_EBREAKH_LENGTH 1
#define CSR_DCSR_EBREAKH (0x1U << CSR_DCSR_EBREAKH_OFFSET)
/*
* When 1, {\tt ebreak} instructions in Supervisor Mode enter Debug Mode. * When 1, {\tt ebreak} instructions in Supervisor Mode enter Debug Mode.
*/ */
#define CSR_DCSR_EBREAKS_OFFSET 13 #define CSR_DCSR_EBREAKS_OFFSET 13
@ -207,9 +201,10 @@
/* /*
* 0: Increment counters as usual. * 0: Increment counters as usual.
* *
* 1: Don't increment any counters while in Debug Mode. This includes * 1: Don't increment any counters while in Debug Mode or on {\tt
* the {\tt cycle} and {\tt instret} CSRs. This is preferred for most * ebreak} instructions that cause entry into Debug Mode. These
* debugging scenarios. * counters include the {\tt cycle} and {\tt instret} CSRs. This is
* preferred for most debugging scenarios.
* *
* An implementation may choose not to support writing to this bit. * An implementation may choose not to support writing to this bit.
* The debugger must read back the value it writes to check whether * The debugger must read back the value it writes to check whether
@ -312,9 +307,9 @@
* *
* This bit is only writable from Debug Mode. * This bit is only writable from Debug Mode.
*/ */
#define CSR_TDATA1_HMODE_OFFSET XLEN-5 #define CSR_TDATA1_DMODE_OFFSET XLEN-5
#define CSR_TDATA1_HMODE_LENGTH 1 #define CSR_TDATA1_DMODE_LENGTH 1
#define CSR_TDATA1_HMODE (0x1ULL << CSR_TDATA1_HMODE_OFFSET) #define CSR_TDATA1_DMODE (0x1ULL << CSR_TDATA1_DMODE_OFFSET)
/* /*
* Trigger-specific data. * Trigger-specific data.
*/ */
@ -390,7 +385,7 @@
* 0: Raise a breakpoint exception. (Used when software wants to use * 0: Raise a breakpoint exception. (Used when software wants to use
* the trigger module without an external debugger attached.) * the trigger module without an external debugger attached.)
* *
* 1: Enter Debug Mode. (Only supported when \Fhmode is 1.) * 1: Enter Debug Mode. (Only supported when \Fdmode is 1.)
* *
* 2: Start tracing. * 2: Start tracing.
* *
@ -532,7 +527,7 @@
* 0: Raise a breakpoint exception. (Used when software wants to use the * 0: Raise a breakpoint exception. (Used when software wants to use the
* trigger module without an external debugger attached.) * trigger module without an external debugger attached.)
* *
* 1: Enter Debug Mode. (Only supported when \Fhmode is 1.) * 1: Enter Debug Mode. (Only supported when \Fdmode is 1.)
* *
* 2: Start tracing. * 2: Start tracing.
* *
@ -549,6 +544,30 @@
#define CSR_ICOUNT_ACTION (0x3fULL << CSR_ICOUNT_ACTION_OFFSET) #define CSR_ICOUNT_ACTION (0x3fULL << CSR_ICOUNT_ACTION_OFFSET)
#define DMI_DMSTATUS 0x11 #define DMI_DMSTATUS 0x11
/* /*
* If 1, then there is an implicit {\tt ebreak} instruction at the
* non-existent word immediately after the Program Buffer. This saves
* the debugger from having to write the {\tt ebreak} itself, and
* allows the Program Buffer to be one word smaller.
*
* This must be 1 when \Fprogbufsize is 1.
*/
#define DMI_DMSTATUS_IMPEBREAK_OFFSET 22
#define DMI_DMSTATUS_IMPEBREAK_LENGTH 1
#define DMI_DMSTATUS_IMPEBREAK (0x1U << DMI_DMSTATUS_IMPEBREAK_OFFSET)
/*
* Gets set if the Debug Module was accessed incorrectly.
*
* 0 (none): No error.
*
* 1 (badaddr): There was an access to an unimplemented Debug Module
* address.
*
* 7 (other): An access failed for another reason.
*/
#define DMI_DMSTATUS_DMERR_OFFSET 18
#define DMI_DMSTATUS_DMERR_LENGTH 3
#define DMI_DMSTATUS_DMERR (0x7U << DMI_DMSTATUS_DMERR_OFFSET)
/*
* This field is 1 when all currently selected harts have acknowledged the previous \Fresumereq. * This field is 1 when all currently selected harts have acknowledged the previous \Fresumereq.
*/ */
#define DMI_DMSTATUS_ALLRESUMEACK_OFFSET 17 #define DMI_DMSTATUS_ALLRESUMEACK_OFFSET 17
@ -629,6 +648,13 @@
#define DMI_DMSTATUS_AUTHBUSY_OFFSET 6 #define DMI_DMSTATUS_AUTHBUSY_OFFSET 6
#define DMI_DMSTATUS_AUTHBUSY_LENGTH 1 #define DMI_DMSTATUS_AUTHBUSY_LENGTH 1
#define DMI_DMSTATUS_AUTHBUSY (0x1U << DMI_DMSTATUS_AUTHBUSY_OFFSET) #define DMI_DMSTATUS_AUTHBUSY (0x1U << DMI_DMSTATUS_AUTHBUSY_OFFSET)
/*
* 0: \Rdevtreeaddrzero--\Rdevtreeaddrthree hold information which
* is not relevant to the Device Tree.
*
* 1: \Rdevtreeaddrzero--\Rdevtreeaddrthree registers hold the address of the
* Device Tree.
*/
#define DMI_DMSTATUS_DEVTREEVALID_OFFSET 4 #define DMI_DMSTATUS_DEVTREEVALID_OFFSET 4
#define DMI_DMSTATUS_DEVTREEVALID_LENGTH 1 #define DMI_DMSTATUS_DEVTREEVALID_LENGTH 1
#define DMI_DMSTATUS_DEVTREEVALID (0x1U << DMI_DMSTATUS_DEVTREEVALID_OFFSET) #define DMI_DMSTATUS_DEVTREEVALID (0x1U << DMI_DMSTATUS_DEVTREEVALID_OFFSET)
@ -654,7 +680,6 @@
* *
* Writing 1 or 0 has no effect on a hart which is already halted, but * Writing 1 or 0 has no effect on a hart which is already halted, but
* the bit should be cleared to 0 before the hart is resumed. * the bit should be cleared to 0 before the hart is resumed.
* Setting both \Fhaltreq and \Fresumereq leads to undefined behavior.
* *
* Writes apply to the new value of \Fhartsel and \Fhasel. * Writes apply to the new value of \Fhartsel and \Fhasel.
*/ */
@ -664,7 +689,8 @@
/* /*
* Resume request signal for all currently selected harts. When set to 1, * Resume request signal for all currently selected harts. When set to 1,
* each selected hart will resume if it is currently halted. * each selected hart will resume if it is currently halted.
* Setting both \Fhaltreq and \Fresumereq leads to undefined behavior. *
* This bit is ignored while \Fhaltreq is set.
* *
* Writes apply to the new value of \Fhartsel and \Fhasel. * Writes apply to the new value of \Fhartsel and \Fhasel.
*/ */
@ -710,11 +736,12 @@
#define DMI_DMCONTROL_HARTSEL (0x3ffU << DMI_DMCONTROL_HARTSEL_OFFSET) #define DMI_DMCONTROL_HARTSEL (0x3ffU << DMI_DMCONTROL_HARTSEL_OFFSET)
/* /*
* This bit controls the reset signal from the DM to the rest of the * This bit controls the reset signal from the DM to the rest of the
* system. To perform a system reset the debugger writes 1, * system. The signal should reset every part of the system, including
* every hart, except for the DM and any logic required to access the
* DM.
* To perform a system reset the debugger writes 1,
* and then writes 0 * and then writes 0
* to deassert the reset. This bit must not reset the Debug Module * to deassert the reset.
* registers. What it does reset is platform-specific (it may
* reset nothing).
*/ */
#define DMI_DMCONTROL_NDMRESET_OFFSET 1 #define DMI_DMCONTROL_NDMRESET_OFFSET 1
#define DMI_DMCONTROL_NDMRESET_LENGTH 1 #define DMI_DMCONTROL_NDMRESET_LENGTH 1
@ -778,7 +805,7 @@
* shadowing the {\tt data} registers. * shadowing the {\tt data} registers.
* *
* If \Fdataaccess is 1: Signed address of RAM where the {\tt data} * If \Fdataaccess is 1: Signed address of RAM where the {\tt data}
* registers are shadowed. * registers are shadowed, to be used to access relative to \Rzero.
*/ */
#define DMI_HARTINFO_DATAADDR_OFFSET 0 #define DMI_HARTINFO_DATAADDR_OFFSET 0
#define DMI_HARTINFO_DATAADDR_LENGTH 12 #define DMI_HARTINFO_DATAADDR_LENGTH 12
@ -891,13 +918,10 @@
#define DMI_ABSTRACTCS 0x16 #define DMI_ABSTRACTCS 0x16
/* /*
* Size of the Program Buffer, in 32-bit words. Valid sizes are 0 - 16. * Size of the Program Buffer, in 32-bit words. Valid sizes are 0 - 16.
*
* TODO: Explain what can be done with each size of the buffer, to suggest
* why you would want more or less words.
*/ */
#define DMI_ABSTRACTCS_PROGSIZE_OFFSET 24 #define DMI_ABSTRACTCS_PROGBUFSIZE_OFFSET 24
#define DMI_ABSTRACTCS_PROGSIZE_LENGTH 5 #define DMI_ABSTRACTCS_PROGBUFSIZE_LENGTH 5
#define DMI_ABSTRACTCS_PROGSIZE (0x1fU << DMI_ABSTRACTCS_PROGSIZE_OFFSET) #define DMI_ABSTRACTCS_PROGBUFSIZE (0x1fU << DMI_ABSTRACTCS_PROGBUFSIZE_OFFSET)
/* /*
* 1: An abstract command is currently being executed. * 1: An abstract command is currently being executed.
* *
@ -1013,24 +1037,22 @@
* *
* 4: 128-bit * 4: 128-bit
* *
* If an unsupported system bus access size is written here, * If an unsupported system bus access size is written here, the DM
* the DM may not perform the access, or may perform the access * does not perform the access and sberror is set to 3.
* with any access size.
*/ */
#define DMI_SBCS_SBACCESS_OFFSET 17 #define DMI_SBCS_SBACCESS_OFFSET 17
#define DMI_SBCS_SBACCESS_LENGTH 3 #define DMI_SBCS_SBACCESS_LENGTH 3
#define DMI_SBCS_SBACCESS (0x7U << DMI_SBCS_SBACCESS_OFFSET) #define DMI_SBCS_SBACCESS (0x7U << DMI_SBCS_SBACCESS_OFFSET)
/* /*
* When 1, the internal address value (used by the system bus master) * When 1, {\tt sbaddress} is incremented by the access size (in
* is incremented by the access size (in bytes) selected in \Fsbaccess * bytes) selected in \Fsbaccess after every system bus access.
* after every system bus access.
*/ */
#define DMI_SBCS_SBAUTOINCREMENT_OFFSET 16 #define DMI_SBCS_SBAUTOINCREMENT_OFFSET 16
#define DMI_SBCS_SBAUTOINCREMENT_LENGTH 1 #define DMI_SBCS_SBAUTOINCREMENT_LENGTH 1
#define DMI_SBCS_SBAUTOINCREMENT (0x1U << DMI_SBCS_SBAUTOINCREMENT_OFFSET) #define DMI_SBCS_SBAUTOINCREMENT (0x1U << DMI_SBCS_SBAUTOINCREMENT_OFFSET)
/* /*
* When 1, every read from \Rsbdatazero automatically triggers a system * When 1, every read from \Rsbdatazero automatically triggers a
* bus read at the new address. * system bus read at the (possibly auto-incremented) address.
*/ */
#define DMI_SBCS_SBAUTOREAD_OFFSET 15 #define DMI_SBCS_SBAUTOREAD_OFFSET 15
#define DMI_SBCS_SBAUTOREAD_LENGTH 1 #define DMI_SBCS_SBAUTOREAD_LENGTH 1
@ -1052,8 +1074,7 @@
* *
* 4: The system bus master was busy when one of the * 4: The system bus master was busy when one of the
* {\tt sbaddress} or {\tt sbdata} registers was written, * {\tt sbaddress} or {\tt sbdata} registers was written,
* or the {\tt sbdata} register was read when it had * or \Rsbdatazero was read when it had stale data.
* stale data.
*/ */
#define DMI_SBCS_SBERROR_OFFSET 12 #define DMI_SBCS_SBERROR_OFFSET 12
#define DMI_SBCS_SBERROR_LENGTH 3 #define DMI_SBCS_SBERROR_LENGTH 3
@ -1097,54 +1118,54 @@
#define DMI_SBCS_SBACCESS8 (0x1U << DMI_SBCS_SBACCESS8_OFFSET) #define DMI_SBCS_SBACCESS8 (0x1U << DMI_SBCS_SBACCESS8_OFFSET)
#define DMI_SBADDRESS0 0x39 #define DMI_SBADDRESS0 0x39
/* /*
* Accesses bits 31:0 of the internal address. * Accesses bits 31:0 of the physical address in {\tt sbaddress}.
*/ */
#define DMI_SBADDRESS0_ADDRESS_OFFSET 0 #define DMI_SBADDRESS0_ADDRESS_OFFSET 0
#define DMI_SBADDRESS0_ADDRESS_LENGTH 32 #define DMI_SBADDRESS0_ADDRESS_LENGTH 32
#define DMI_SBADDRESS0_ADDRESS (0xffffffffU << DMI_SBADDRESS0_ADDRESS_OFFSET) #define DMI_SBADDRESS0_ADDRESS (0xffffffffU << DMI_SBADDRESS0_ADDRESS_OFFSET)
#define DMI_SBADDRESS1 0x3a #define DMI_SBADDRESS1 0x3a
/* /*
* Accesses bits 63:32 of the internal address (if the system address * Accesses bits 63:32 of the physical address in {\tt sbaddress} (if
* bus is that wide). * the system address bus is that wide).
*/ */
#define DMI_SBADDRESS1_ADDRESS_OFFSET 0 #define DMI_SBADDRESS1_ADDRESS_OFFSET 0
#define DMI_SBADDRESS1_ADDRESS_LENGTH 32 #define DMI_SBADDRESS1_ADDRESS_LENGTH 32
#define DMI_SBADDRESS1_ADDRESS (0xffffffffU << DMI_SBADDRESS1_ADDRESS_OFFSET) #define DMI_SBADDRESS1_ADDRESS (0xffffffffU << DMI_SBADDRESS1_ADDRESS_OFFSET)
#define DMI_SBADDRESS2 0x3b #define DMI_SBADDRESS2 0x3b
/* /*
* Accesses bits 95:64 of the internal address (if the system address * Accesses bits 95:64 of the physical address in {\tt sbaddress} (if
* bus is that wide). * the system address bus is that wide).
*/ */
#define DMI_SBADDRESS2_ADDRESS_OFFSET 0 #define DMI_SBADDRESS2_ADDRESS_OFFSET 0
#define DMI_SBADDRESS2_ADDRESS_LENGTH 32 #define DMI_SBADDRESS2_ADDRESS_LENGTH 32
#define DMI_SBADDRESS2_ADDRESS (0xffffffffU << DMI_SBADDRESS2_ADDRESS_OFFSET) #define DMI_SBADDRESS2_ADDRESS (0xffffffffU << DMI_SBADDRESS2_ADDRESS_OFFSET)
#define DMI_SBDATA0 0x3c #define DMI_SBDATA0 0x3c
/* /*
* Accesses bits 31:0 of the internal data. * Accesses bits 31:0 of {\tt sbdata}.
*/ */
#define DMI_SBDATA0_DATA_OFFSET 0 #define DMI_SBDATA0_DATA_OFFSET 0
#define DMI_SBDATA0_DATA_LENGTH 32 #define DMI_SBDATA0_DATA_LENGTH 32
#define DMI_SBDATA0_DATA (0xffffffffU << DMI_SBDATA0_DATA_OFFSET) #define DMI_SBDATA0_DATA (0xffffffffU << DMI_SBDATA0_DATA_OFFSET)
#define DMI_SBDATA1 0x3d #define DMI_SBDATA1 0x3d
/* /*
* Accesses bits 63:32 of the internal data (if the system bus is * Accesses bits 63:32 of {\tt sbdata} (if the system bus is that
* that wide). * wide).
*/ */
#define DMI_SBDATA1_DATA_OFFSET 0 #define DMI_SBDATA1_DATA_OFFSET 0
#define DMI_SBDATA1_DATA_LENGTH 32 #define DMI_SBDATA1_DATA_LENGTH 32
#define DMI_SBDATA1_DATA (0xffffffffU << DMI_SBDATA1_DATA_OFFSET) #define DMI_SBDATA1_DATA (0xffffffffU << DMI_SBDATA1_DATA_OFFSET)
#define DMI_SBDATA2 0x3e #define DMI_SBDATA2 0x3e
/* /*
* Accesses bits 95:64 of the internal data (if the system bus is * Accesses bits 95:64 of {\tt sbdata} (if the system bus is that
* that wide). * wide).
*/ */
#define DMI_SBDATA2_DATA_OFFSET 0 #define DMI_SBDATA2_DATA_OFFSET 0
#define DMI_SBDATA2_DATA_LENGTH 32 #define DMI_SBDATA2_DATA_LENGTH 32
#define DMI_SBDATA2_DATA (0xffffffffU << DMI_SBDATA2_DATA_OFFSET) #define DMI_SBDATA2_DATA (0xffffffffU << DMI_SBDATA2_DATA_OFFSET)
#define DMI_SBDATA3 0x3f #define DMI_SBDATA3 0x3f
/* /*
* Accesses bits 127:96 of the internal data (if the system bus is * Accesses bits 127:96 of {\tt sbdata} (if the system bus is that
* that wide). * wide).
*/ */
#define DMI_SBDATA3_DATA_OFFSET 0 #define DMI_SBDATA3_DATA_OFFSET 0
#define DMI_SBDATA3_DATA_LENGTH 32 #define DMI_SBDATA3_DATA_LENGTH 32
@ -1188,6 +1209,9 @@
* 0: Don't do the operation specified by \Fwrite. * 0: Don't do the operation specified by \Fwrite.
* *
* 1: Do the operation specified by \Fwrite. * 1: Do the operation specified by \Fwrite.
*
* This bit can be used to just execute the Program Buffer without
* having to worry about placing valid values into \Fsize or \Fregno.
*/ */
#define AC_ACCESS_REGISTER_TRANSFER_OFFSET 17 #define AC_ACCESS_REGISTER_TRANSFER_OFFSET 17
#define AC_ACCESS_REGISTER_TRANSFER_LENGTH 1 #define AC_ACCESS_REGISTER_TRANSFER_LENGTH 1
@ -1223,8 +1247,9 @@
/* /*
* Contains the privilege level the hart was operating in when Debug * Contains the privilege level the hart was operating in when Debug
* Mode was entered. The encoding is described in Table * Mode was entered. The encoding is described in Table
* \ref{tab:privlevel}. A user can write this value to change the * \ref{tab:privlevel}, and matches the privilege level encoding from
* hart's privilege level when exiting Debug Mode. * the RISC-V Privileged ISA Specification. A user can write this
* value to change the hart's privilege level when exiting Debug Mode.
*/ */
#define VIRT_PRIV_PRV_OFFSET 0 #define VIRT_PRIV_PRV_OFFSET 0
#define VIRT_PRIV_PRV_LENGTH 2 #define VIRT_PRIV_PRV_LENGTH 2

View File

@ -11,44 +11,39 @@
#include "asm.h" #include "asm.h"
#include "encoding.h" #include "encoding.h"
riscv_addr_t riscv_program_gal(struct riscv_program *p, riscv_addr_t addr);
int riscv_program_lah(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr);
int riscv_program_lal(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr);
/* Program interface. */ /* Program interface. */
int riscv_program_init(struct riscv_program *p, struct target *target) int riscv_program_init(struct riscv_program *p, struct target *target)
{ {
memset(p, 0, sizeof(*p)); memset(p, 0, sizeof(*p));
p->target = target; p->target = target;
p->instruction_count = 0; p->instruction_count = 0;
p->data_count = 0;
p->writes_memory = 0;
p->target_xlen = riscv_xlen(target); p->target_xlen = riscv_xlen(target);
for (size_t i = 0; i < RISCV_REGISTER_COUNT; ++i) { for (size_t i = 0; i < RISCV_REGISTER_COUNT; ++i) {
p->writes_xreg[i] = 0; p->writes_xreg[i] = 0;
p->in_use[i] = 0;
} }
for(size_t i = 0; i < RISCV_MAX_DEBUG_BUFFER_SIZE; ++i) for(size_t i = 0; i < RISCV_MAX_DEBUG_BUFFER_SIZE; ++i)
p->debug_buffer[i] = -1; p->debug_buffer[i] = -1;
if (riscv_debug_buffer_enter(target, p) != ERROR_OK) {
LOG_ERROR("unable to write progam buffer enter code");
return ERROR_FAIL;
}
return ERROR_OK; return ERROR_OK;
} }
int riscv_program_write(struct riscv_program *program)
{
for (unsigned i = 0; i < program->instruction_count; ++i) {
LOG_DEBUG("%p: debug_buffer[%02x] = DASM(0x%08x)", program, i, program->debug_buffer[i]);
if (riscv_write_debug_buffer(program->target, i,
program->debug_buffer[i]) != ERROR_OK)
return ERROR_FAIL;
}
return ERROR_OK;
}
/** Add ebreak and execute the program. */
int riscv_program_exec(struct riscv_program *p, struct target *t) int riscv_program_exec(struct riscv_program *p, struct target *t)
{ {
keep_alive(); keep_alive();
if (riscv_debug_buffer_leave(t, p) != ERROR_OK) {
LOG_ERROR("unable to write program buffer exit code");
return ERROR_FAIL;
}
riscv_reg_t saved_registers[GDB_REGNO_XPR31 + 1]; riscv_reg_t saved_registers[GDB_REGNO_XPR31 + 1];
for (size_t i = GDB_REGNO_XPR0 + 1; i <= GDB_REGNO_XPR31; ++i) { for (size_t i = GDB_REGNO_XPR0 + 1; i <= GDB_REGNO_XPR31; ++i) {
if (p->writes_xreg[i]) { if (p->writes_xreg[i]) {
@ -57,14 +52,6 @@ int riscv_program_exec(struct riscv_program *p, struct target *t)
} }
} }
if (p->writes_memory && (riscv_program_fence(p) != ERROR_OK)) {
LOG_ERROR("Unable to write fence");
for(size_t i = 0; i < riscv_debug_buffer_size(p->target); ++i)
LOG_ERROR("ram[%02x]: DASM(0x%08lx) [0x%08lx]", (int)i, (long)p->debug_buffer[i], (long)p->debug_buffer[i]);
abort();
return ERROR_FAIL;
}
if (riscv_program_ebreak(p) != ERROR_OK) { if (riscv_program_ebreak(p) != ERROR_OK) {
LOG_ERROR("Unable to write ebreak"); LOG_ERROR("Unable to write ebreak");
for(size_t i = 0; i < riscv_debug_buffer_size(p->target); ++i) for(size_t i = 0; i < riscv_debug_buffer_size(p->target); ++i)
@ -73,16 +60,8 @@ int riscv_program_exec(struct riscv_program *p, struct target *t)
return ERROR_FAIL; return ERROR_FAIL;
} }
for (unsigned i = 0; i < riscv_debug_buffer_size(p->target); ++i) { if (riscv_program_write(p) != ERROR_OK)
if (i < p->instruction_count) { return ERROR_FAIL;
LOG_DEBUG("%p: debug_buffer[%02x] = DASM(0x%08x)", p, i, p->debug_buffer[i]);
riscv_write_debug_buffer(t, i, p->debug_buffer[i]);
}
if (i >= riscv_debug_buffer_size(p->target) - p->data_count) {
LOG_DEBUG("%p: debug_buffer[%02x] = 0x%08x", p, i, p->debug_buffer[i]);
riscv_write_debug_buffer(t, i, p->debug_buffer[i]);
}
}
if (riscv_execute_debug_buffer(t) != ERROR_OK) { if (riscv_execute_debug_buffer(t) != ERROR_OK) {
LOG_ERROR("Unable to execute program %p", p); LOG_ERROR("Unable to execute program %p", p);
@ -90,7 +69,7 @@ int riscv_program_exec(struct riscv_program *p, struct target *t)
} }
for (size_t i = 0; i < riscv_debug_buffer_size(p->target); ++i) for (size_t i = 0; i < riscv_debug_buffer_size(p->target); ++i)
if (i >= riscv_debug_buffer_size(p->target) - p->data_count) if (i >= riscv_debug_buffer_size(p->target))
p->debug_buffer[i] = riscv_read_debug_buffer(t, i); p->debug_buffer[i] = riscv_read_debug_buffer(t, i);
for (size_t i = GDB_REGNO_XPR0; i <= GDB_REGNO_XPR31; ++i) for (size_t i = GDB_REGNO_XPR0; i <= GDB_REGNO_XPR31; ++i)
@ -100,236 +79,39 @@ int riscv_program_exec(struct riscv_program *p, struct target *t)
return ERROR_OK; 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) int riscv_program_swr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int offset)
{ {
p->writes_memory = 1;
return riscv_program_insert(p, sw(d, b, offset)); return riscv_program_insert(p, sw(d, b, offset));
} }
int riscv_program_shr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int offset) int riscv_program_shr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int offset)
{ {
p->writes_memory = 1;
return riscv_program_insert(p, sh(d, b, offset)); return riscv_program_insert(p, sh(d, b, offset));
} }
int riscv_program_sbr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int offset) int riscv_program_sbr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int offset)
{ {
p->writes_memory = 1;
return riscv_program_insert(p, sb(d, b, offset)); return riscv_program_insert(p, sb(d, b, offset));
} }
int riscv_program_lwr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int offset) int riscv_program_lwr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int offset)
{ {
p->writes_memory = 1;
return riscv_program_insert(p, lw(d, b, offset)); return riscv_program_insert(p, lw(d, b, offset));
} }
int riscv_program_lhr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int offset) int riscv_program_lhr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int offset)
{ {
p->writes_memory = 1;
return riscv_program_insert(p, lh(d, b, offset)); return riscv_program_insert(p, lh(d, b, offset));
} }
int riscv_program_lbr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int offset) int riscv_program_lbr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno b, int offset)
{ {
p->writes_memory = 1;
return riscv_program_insert(p, lb(d, b, offset)); return riscv_program_insert(p, lb(d, b, offset));
} }
int riscv_program_lx(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr)
{
switch (p->target_xlen) {
case 64: return riscv_program_ld(p, d, addr);
case 32: return riscv_program_lw(p, d, addr);
}
LOG_ERROR("unknown xlen %d", p->target_xlen);
abort();
return -1;
}
int riscv_program_ld(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr)
{
enum gdb_regno t = riscv_program_gah(p, addr) == 0 ? GDB_REGNO_X0 : d;
if (riscv_program_lah(p, d, addr) != ERROR_OK)
return ERROR_FAIL;
if (riscv_program_insert(p, ld(d, t, riscv_program_gal(p, addr))) != ERROR_OK)
return ERROR_FAIL;
return ERROR_OK;
}
int riscv_program_lw(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr)
{
enum gdb_regno t = riscv_program_gah(p, addr) == 0 ? GDB_REGNO_X0 : d;
if (riscv_program_lah(p, d, addr) != ERROR_OK)
return ERROR_FAIL;
if (riscv_program_insert(p, lw(d, t, riscv_program_gal(p, addr))) != ERROR_OK)
return ERROR_FAIL;
return ERROR_OK;
}
int riscv_program_lh(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr)
{
enum gdb_regno t = riscv_program_gah(p, addr) == 0 ? GDB_REGNO_X0 : d;
if (riscv_program_lah(p, d, addr) != ERROR_OK)
return ERROR_FAIL;
if (riscv_program_insert(p, lh(d, t, riscv_program_gal(p, addr))) != ERROR_OK)
return ERROR_FAIL;
return ERROR_OK;
}
int riscv_program_lb(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr)
{
enum gdb_regno t = riscv_program_gah(p, addr) == 0 ? GDB_REGNO_X0 : d;
if (riscv_program_lah(p, t, addr) != ERROR_OK)
return ERROR_FAIL;
if (riscv_program_insert(p, lb(d, t, riscv_program_gal(p, addr))) != ERROR_OK)
return ERROR_FAIL;
return ERROR_OK;
}
int riscv_program_sx(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr)
{
switch (p->target_xlen) {
case 64: return riscv_program_sd(p, d, addr);
case 32: return riscv_program_sw(p, d, addr);
}
LOG_ERROR("unknown xlen %d", p->target_xlen);
abort();
return -1;
}
int riscv_program_sd(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr)
{
enum gdb_regno t = riscv_program_gah(p, addr) == 0
? GDB_REGNO_X0
: riscv_program_gettemp(p);
if (riscv_program_lah(p, t, addr) != ERROR_OK)
return ERROR_FAIL;
if (riscv_program_insert(p, sd(d, t, riscv_program_gal(p, addr))) != ERROR_OK)
return ERROR_FAIL;
riscv_program_puttemp(p, t);
p->writes_memory = true;
return ERROR_OK;
}
int riscv_program_sw(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr)
{
enum gdb_regno t = riscv_program_gah(p, addr) == 0
? GDB_REGNO_X0
: riscv_program_gettemp(p);
if (riscv_program_lah(p, t, addr) != ERROR_OK)
return ERROR_FAIL;
if (riscv_program_insert(p, sw(d, t, riscv_program_gal(p, addr))) != ERROR_OK)
return ERROR_FAIL;
riscv_program_puttemp(p, t);
p->writes_memory = true;
return ERROR_OK;
}
int riscv_program_sh(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr)
{
enum gdb_regno t = riscv_program_gah(p, addr) == 0
? GDB_REGNO_X0
: riscv_program_gettemp(p);
if (riscv_program_lah(p, t, addr) != ERROR_OK)
return ERROR_FAIL;
if (riscv_program_insert(p, sh(d, t, riscv_program_gal(p, addr))) != ERROR_OK)
return ERROR_FAIL;
riscv_program_puttemp(p, t);
p->writes_memory = true;
return ERROR_OK;
}
int riscv_program_sb(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr)
{
enum gdb_regno t = riscv_program_gah(p, addr) == 0
? GDB_REGNO_X0
: riscv_program_gettemp(p);
if (riscv_program_lah(p, t, addr) != ERROR_OK)
return ERROR_FAIL;
if (riscv_program_insert(p, sb(d, t, riscv_program_gal(p, addr))) != ERROR_OK)
return ERROR_FAIL;
riscv_program_puttemp(p, t);
p->writes_memory = true;
return ERROR_OK;
}
int riscv_program_csrr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno csr) int riscv_program_csrr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno csr)
{ {
assert(csr >= GDB_REGNO_CSR0); assert(csr >= GDB_REGNO_CSR0 && csr <= GDB_REGNO_CSR4095);
return riscv_program_insert(p, csrrs(d, GDB_REGNO_X0, csr - GDB_REGNO_CSR0)); return riscv_program_insert(p, csrrs(d, GDB_REGNO_X0, csr - GDB_REGNO_CSR0));
} }
@ -339,12 +121,6 @@ int riscv_program_csrw(struct riscv_program *p, enum gdb_regno s, enum gdb_regno
return riscv_program_insert(p, csrrw(GDB_REGNO_X0, s, csr - GDB_REGNO_CSR0)); return riscv_program_insert(p, csrrw(GDB_REGNO_X0, s, csr - GDB_REGNO_CSR0));
} }
int riscv_program_csrrw(struct riscv_program *p, enum gdb_regno d, enum gdb_regno s, enum gdb_regno csr)
{
assert(csr >= GDB_REGNO_CSR0);
return riscv_program_insert(p, csrrw(d, s, csr - GDB_REGNO_CSR0));
}
int riscv_program_fence_i(struct riscv_program *p) int riscv_program_fence_i(struct riscv_program *p)
{ {
return riscv_program_insert(p, fence_i()); return riscv_program_insert(p, fence_i());
@ -357,158 +133,27 @@ int riscv_program_fence(struct riscv_program *p)
int riscv_program_ebreak(struct riscv_program *p) int riscv_program_ebreak(struct riscv_program *p)
{ {
struct target *target = p->target;
RISCV_INFO(r);
if (p->instruction_count == riscv_debug_buffer_size(p->target) &&
r->impebreak) {
return ERROR_OK;
}
return riscv_program_insert(p, ebreak()); return riscv_program_insert(p, ebreak());
} }
int riscv_program_lui(struct riscv_program *p, enum gdb_regno d, int32_t u)
{
return riscv_program_insert(p, lui(d, u));
}
int riscv_program_addi(struct riscv_program *p, enum gdb_regno d, enum gdb_regno s, int16_t u) int riscv_program_addi(struct riscv_program *p, enum gdb_regno d, enum gdb_regno s, int16_t u)
{ {
return riscv_program_insert(p, addi(d, s, u)); return riscv_program_insert(p, addi(d, s, u));
} }
int riscv_program_fsx(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr)
{
assert(d >= GDB_REGNO_FPR0);
assert(d <= GDB_REGNO_FPR31);
enum gdb_regno t = riscv_program_gah(p, addr) == 0
? GDB_REGNO_X0
: riscv_program_gettemp(p);
if (riscv_program_lah(p, t, addr) != ERROR_OK)
return ERROR_FAIL;
uint32_t instruction;
switch (p->target->reg_cache->reg_list[GDB_REGNO_FPR0].size) {
case 64:
instruction = fsd(d - GDB_REGNO_FPR0, t, riscv_program_gal(p, addr));
break;
case 32:
instruction = fsw(d - GDB_REGNO_FPR0, t, riscv_program_gal(p, addr));
break;
default:
return ERROR_FAIL;
}
if (riscv_program_insert(p, instruction) != ERROR_OK)
return ERROR_FAIL;
riscv_program_puttemp(p, t);
p->writes_memory = true;
return ERROR_OK;
}
int riscv_program_flx(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr)
{
assert(d >= GDB_REGNO_FPR0);
assert(d <= GDB_REGNO_FPR31);
enum gdb_regno t = riscv_program_gah(p, addr) == 0 ? GDB_REGNO_X0 : d;
if (riscv_program_lah(p, t, addr) != ERROR_OK)
return ERROR_FAIL;
uint32_t instruction;
switch (p->target->reg_cache->reg_list[GDB_REGNO_FPR0].size) {
case 64:
instruction = fld(d - GDB_REGNO_FPR0, t, riscv_program_gal(p, addr));
break;
case 32:
instruction = flw(d - GDB_REGNO_FPR0, t, riscv_program_gal(p, addr));
break;
default:
return ERROR_FAIL;
}
if (riscv_program_insert(p, instruction) != ERROR_OK)
return ERROR_FAIL;
return ERROR_OK;
}
int riscv_program_li(struct riscv_program *p, enum gdb_regno d, riscv_reg_t c)
{
if (riscv_program_lui(p, d, c >> 12) != ERROR_OK)
return ERROR_FAIL;
if (riscv_program_addi(p, d, d, c & 0xFFF) != ERROR_OK)
return ERROR_FAIL;
return ERROR_OK;
}
int riscv_program_dont_restore_register(struct riscv_program *p, enum gdb_regno r)
{
assert(r < RISCV_REGISTER_COUNT);
p->writes_xreg[r] = 0;
return ERROR_OK;
}
int riscv_program_do_restore_register(struct riscv_program *p, enum gdb_regno r)
{
assert(r < RISCV_REGISTER_COUNT);
p->writes_xreg[r] = 1;
return ERROR_OK;
}
void riscv_program_reserve_register(struct riscv_program *p, enum gdb_regno r)
{
assert(r < RISCV_REGISTER_COUNT);
assert(p->in_use[r] == 0);
p->in_use[r] = 1;
}
enum gdb_regno riscv_program_gettemp(struct riscv_program *p)
{
for (size_t i = GDB_REGNO_S0; i <= GDB_REGNO_XPR31; ++i) {
if (p->in_use[i]) continue;
riscv_program_do_restore_register(p, i);
p->in_use[i] = 1;
return i;
}
LOG_ERROR("You've run out of temporary registers. This is impossible.");
abort();
}
void riscv_program_puttemp(struct riscv_program *p, enum gdb_regno r)
{
assert(r < RISCV_REGISTER_COUNT);
p->in_use[r] = 0;
}
/* Helper functions. */
riscv_addr_t riscv_program_gah(struct riscv_program *p, riscv_addr_t addr)
{
return addr >> 12;
}
riscv_addr_t riscv_program_gal(struct riscv_program *p, riscv_addr_t addr)
{
if (addr > 0) {
return (addr & 0x7FF);
} else {
return 0;
}
}
int riscv_program_lah(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr)
{
riscv_addr_t ah = riscv_program_gah(p, addr);
if (ah == 0)
return ERROR_OK;
return riscv_program_lui(p, d, ah);
}
int riscv_program_lal(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr)
{
riscv_addr_t al = riscv_program_gal(p, addr);
if (al == 0)
return ERROR_OK;
return riscv_program_addi(p, d, d, al);
}
int riscv_program_insert(struct riscv_program *p, riscv_insn_t i) int riscv_program_insert(struct riscv_program *p, riscv_insn_t i)
{ {
if (p->instruction_count + p->data_count + 1 > riscv_debug_buffer_size(p->target)) { if (p->instruction_count >= riscv_debug_buffer_size(p->target)) {
LOG_ERROR("Unable to insert instruction:"); LOG_ERROR("Unable to insert instruction:");
LOG_ERROR(" instruction_count=%d", (int)p->instruction_count); LOG_ERROR(" instruction_count=%d", (int)p->instruction_count);
LOG_ERROR(" data_count =%d", (int)p->data_count);
LOG_ERROR(" buffer size =%d", (int)riscv_debug_buffer_size(p->target)); LOG_ERROR(" buffer size =%d", (int)riscv_debug_buffer_size(p->target));
return ERROR_FAIL; abort();
} }
p->debug_buffer[p->instruction_count] = i; p->debug_buffer[p->instruction_count] = i;

View File

@ -15,23 +15,12 @@ struct riscv_program {
uint32_t debug_buffer[RISCV_MAX_DEBUG_BUFFER_SIZE]; uint32_t debug_buffer[RISCV_MAX_DEBUG_BUFFER_SIZE];
/* The debug buffer is allocated in two directions: instructions go at /* Number of 32-bit instructions in the program. */
* the start, while data goes at the end. When they meet in the middle
* this blows up. */
size_t instruction_count; size_t instruction_count;
size_t data_count;
/* Side effects of executing this program. These must be accounted for /* Side effects of executing this program. These must be accounted for
* in order to maintain correct executing of the target system. */ * in order to maintain correct executing of the target system. */
bool writes_xreg[RISCV_REGISTER_COUNT]; bool writes_xreg[RISCV_REGISTER_COUNT];
bool writes_memory;
/* When a register is used it will be set in this array. */
bool in_use[RISCV_REGISTER_COUNT];
/* Remembers the registers that have been saved into dscratch
* registers. These are restored */
enum gdb_regno dscratch_saved[RISCV_DSCRATCH_COUNT];
/* XLEN on the target. */ /* XLEN on the target. */
int target_xlen; int target_xlen;
@ -40,6 +29,9 @@ struct riscv_program {
/* Initializes a program with the header. */ /* Initializes a program with the header. */
int riscv_program_init(struct riscv_program *p, struct target *t); int riscv_program_init(struct riscv_program *p, struct target *t);
/* Write the program to the program buffer. */
int riscv_program_write(struct riscv_program *program);
/* Executes a program, returning 0 if the program successfully executed. Note /* Executes a program, returning 0 if the program successfully executed. Note
* that this may cause registers to be saved or restored, which could result to * that this may cause registers to be saved or restored, which could result to
* calls to things like riscv_save_register which itself could require a * calls to things like riscv_save_register which itself could require a
@ -60,83 +52,24 @@ int riscv_program_insert(struct riscv_program *p, riscv_insn_t i);
* memory. */ * memory. */
int riscv_program_save_to_dscratch(struct riscv_program *p, enum gdb_regno to_save); 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 /* Helpers to assembly various instructions. Return 0 on success. These might
* assembly into a multi-instruction sequence that overwrites some other * assembly into a multi-instruction sequence that overwrites some other
* register, but those will be properly saved and restored. */ * register, but those will be properly saved and restored. */
int riscv_program_lx(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr);
int riscv_program_ld(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr);
int riscv_program_lw(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr);
int riscv_program_lh(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr);
int riscv_program_lb(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr);
int riscv_program_sx(struct riscv_program *p, enum gdb_regno s, riscv_addr_t addr);
int riscv_program_sd(struct riscv_program *p, enum gdb_regno s, riscv_addr_t addr);
int riscv_program_sw(struct riscv_program *p, enum gdb_regno s, riscv_addr_t addr);
int riscv_program_sh(struct riscv_program *p, enum gdb_regno s, riscv_addr_t addr);
int riscv_program_sb(struct riscv_program *p, enum gdb_regno s, riscv_addr_t addr);
int riscv_program_lxr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno a, int o);
int riscv_program_ldr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno a, int o);
int riscv_program_lwr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno a, int o); int riscv_program_lwr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno a, int o);
int riscv_program_lhr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno a, int o); int riscv_program_lhr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno a, int o);
int riscv_program_lbr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno a, int o); int riscv_program_lbr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno a, int o);
int riscv_program_sxr(struct riscv_program *p, enum gdb_regno s, enum gdb_regno a, int o);
int riscv_program_sdr(struct riscv_program *p, enum gdb_regno s, enum gdb_regno a, int o);
int riscv_program_swr(struct riscv_program *p, enum gdb_regno s, enum gdb_regno a, int o); int riscv_program_swr(struct riscv_program *p, enum gdb_regno s, enum gdb_regno a, int o);
int riscv_program_shr(struct riscv_program *p, enum gdb_regno s, enum gdb_regno a, int o); int riscv_program_shr(struct riscv_program *p, enum gdb_regno s, enum gdb_regno a, int o);
int riscv_program_sbr(struct riscv_program *p, enum gdb_regno s, enum gdb_regno a, int o); int riscv_program_sbr(struct riscv_program *p, enum gdb_regno s, enum gdb_regno a, int o);
int riscv_program_csrr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno csr); int riscv_program_csrr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno csr);
int riscv_program_csrw(struct riscv_program *p, enum gdb_regno s, enum gdb_regno csr); int riscv_program_csrw(struct riscv_program *p, enum gdb_regno s, enum gdb_regno csr);
int riscv_program_csrrw(struct riscv_program *p, enum gdb_regno d, enum gdb_regno s, enum gdb_regno csr);
int riscv_program_fence_i(struct riscv_program *p); int riscv_program_fence_i(struct riscv_program *p);
int riscv_program_fence(struct riscv_program *p); int riscv_program_fence(struct riscv_program *p);
int riscv_program_ebreak(struct riscv_program *p); int riscv_program_ebreak(struct riscv_program *p);
int riscv_program_lui(struct riscv_program *p, enum gdb_regno d, int32_t u);
int riscv_program_addi(struct riscv_program *p, enum gdb_regno d, enum gdb_regno s, int16_t i); int riscv_program_addi(struct riscv_program *p, enum gdb_regno d, enum gdb_regno s, int16_t i);
int riscv_program_fsx(struct riscv_program *p, enum gdb_regno s, riscv_addr_t addr);
int riscv_program_flx(struct riscv_program *p, enum gdb_regno d, riscv_addr_t addr);
/* Assembler macros. */
int riscv_program_li(struct riscv_program *p, enum gdb_regno d, riscv_reg_t c);
int riscv_program_la(struct riscv_program *p, enum gdb_regno d, riscv_addr_t a);
/* Register allocation. The user is expected to have obtained temporary
* registers using these fuctions. Additionally, there is an interface for
* reserving registers -- it's expected that this has been called as the first
* thing in the program's execution to reserve registers that can't be touched
* by the program's execution. */
void riscv_program_reserve_register(struct riscv_program *p, enum gdb_regno r);
enum gdb_regno riscv_program_gettemp(struct riscv_program *p);
void riscv_program_puttemp(struct riscv_program *p, enum gdb_regno r);
/* Executing a program usually causes the registers that get overwritten to be
* saved and restored. Calling this prevents the given register from actually
* being restored as a result of all activity in this program. */
int riscv_program_dont_restore_register(struct riscv_program *p, enum gdb_regno r);
int riscv_program_do_restore_register(struct riscv_program *p, enum gdb_regno r);
/* Addressing functions. */
riscv_addr_t riscv_program_gah(struct riscv_program *p, riscv_addr_t addr);
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -200,6 +200,9 @@ int riscv_command_timeout_sec = DEFAULT_COMMAND_TIMEOUT_SEC;
/* Wall-clock timeout after reset. Settable via RISC-V Target commands.*/ /* Wall-clock timeout after reset. Settable via RISC-V Target commands.*/
int riscv_reset_timeout_sec = DEFAULT_RESET_TIMEOUT_SEC; int riscv_reset_timeout_sec = DEFAULT_RESET_TIMEOUT_SEC;
bool riscv_use_scratch_ram = false;
uint64_t riscv_scratch_ram_address = 0;
static uint32_t dtmcontrol_scan(struct target *target, uint32_t out) static uint32_t dtmcontrol_scan(struct target *target, uint32_t out)
{ {
struct scan_field field; struct scan_field field;
@ -1120,8 +1123,8 @@ int riscv_openocd_step(
} }
/* Command Handlers */ /* Command Handlers */
COMMAND_HANDLER(riscv_set_command_timeout_sec) { COMMAND_HANDLER(riscv_set_command_timeout_sec)
{
if (CMD_ARGC != 1) { if (CMD_ARGC != 1) {
LOG_ERROR("Command takes exactly 1 parameter"); LOG_ERROR("Command takes exactly 1 parameter");
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
@ -1137,11 +1140,11 @@ COMMAND_HANDLER(riscv_set_command_timeout_sec) {
return ERROR_OK; return ERROR_OK;
} }
COMMAND_HANDLER(riscv_set_reset_timeout_sec) { COMMAND_HANDLER(riscv_set_reset_timeout_sec)
{
if (CMD_ARGC != 1) { if (CMD_ARGC != 1) {
LOG_ERROR("Command takes exactly 1 parameter"); LOG_ERROR("Command takes exactly 1 parameter");
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
} }
int timeout = atoi(CMD_ARGV[0]); int timeout = atoi(CMD_ARGV[0]);
if (timeout <= 0){ if (timeout <= 0){
@ -1153,6 +1156,29 @@ COMMAND_HANDLER(riscv_set_reset_timeout_sec) {
return ERROR_OK; return ERROR_OK;
} }
COMMAND_HANDLER(riscv_set_scratch_ram)
{
if (CMD_ARGC != 1) {
LOG_ERROR("Command takes exactly 1 parameter");
return ERROR_COMMAND_SYNTAX_ERROR;
}
if (!strcmp(CMD_ARGV[0], "none")) {
riscv_use_scratch_ram = false;
return ERROR_OK;
}
long long unsigned int address;
int result = sscanf(CMD_ARGV[0], "%Lx", &address);
if (result != (int) strlen(CMD_ARGV[0])) {
LOG_ERROR("%s is not a valid address for command.", CMD_ARGV[0]);
riscv_use_scratch_ram = false;
return ERROR_FAIL;
}
riscv_scratch_ram_address = address;
riscv_use_scratch_ram = true;
return ERROR_OK;
}
static const struct command_registration riscv_exec_command_handlers[] = { static const struct command_registration riscv_exec_command_handlers[] = {
{ {
@ -1161,14 +1187,21 @@ static const struct command_registration riscv_exec_command_handlers[] = {
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.usage = "riscv set_command_timeout_sec [sec]", .usage = "riscv set_command_timeout_sec [sec]",
.help = "Set the wall-clock timeout (in seconds) for individual commands" .help = "Set the wall-clock timeout (in seconds) for individual commands"
}, },
{ {
.name = "set_reset_timeout_sec", .name = "set_reset_timeout_sec",
.handler = riscv_set_reset_timeout_sec, .handler = riscv_set_reset_timeout_sec,
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.usage = "riscv set_reset_timeout_sec [sec]", .usage = "riscv set_reset_timeout_sec [sec]",
.help = "Set the wall-clock timeout (in seconds) after reset is deasserted" .help = "Set the wall-clock timeout (in seconds) after reset is deasserted"
}, },
{
.name = "set_scratch_ram",
.handler = riscv_set_scratch_ram,
.mode = COMMAND_ANY,
.usage = "riscv set_scratch_ram none|[address]",
.help = "Set address of 16 bytes of scratch RAM the debugger can use, or 'none'."
},
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
}; };
@ -1235,7 +1268,6 @@ void riscv_info_init(struct target *target, riscv_info_t *r)
for (size_t h = 0; h < RISCV_MAX_HARTS; ++h) { for (size_t h = 0; h < RISCV_MAX_HARTS; ++h) {
r->xlen[h] = -1; r->xlen[h] = -1;
r->debug_buffer_addr[h] = -1;
for (size_t e = 0; e < RISCV_MAX_REGISTERS; ++e) for (size_t e = 0; e < RISCV_MAX_REGISTERS; ++e)
r->valid_saved_registers[h][e] = false; r->valid_saved_registers[h][e] = false;
@ -1483,28 +1515,6 @@ size_t riscv_debug_buffer_size(struct target *target)
return r->debug_buffer_size[riscv_current_hartid(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);
r->debug_buffer_enter(target, program);
return ERROR_OK;
}
int riscv_debug_buffer_leave(struct target *target, struct riscv_program *program)
{
RISCV_INFO(r);
r->debug_buffer_leave(target, program);
return ERROR_OK;
}
int riscv_write_debug_buffer(struct target *target, int index, riscv_insn_t insn) int riscv_write_debug_buffer(struct target *target, int index, riscv_insn_t insn)
{ {
RISCV_INFO(r); RISCV_INFO(r);

View File

@ -72,15 +72,15 @@ typedef struct {
* target controls, while otherwise only a single hart is controlled. */ * target controls, while otherwise only a single hart is controlled. */
int trigger_unique_id[RISCV_MAX_HWBPS]; 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. */ /* The number of entries in the debug buffer. */
int debug_buffer_size[RISCV_MAX_HARTS]; int debug_buffer_size[RISCV_MAX_HARTS];
/* This avoids invalidating the register cache too often. */ /* This avoids invalidating the register cache too often. */
bool registers_initialized; bool registers_initialized;
/* This hart contains an implicit ebreak at the end of the program buffer. */
bool impebreak;
/* Helper functions that target the various RISC-V debug spec /* Helper functions that target the various RISC-V debug spec
* implementations. */ * implementations. */
riscv_reg_t (*get_register)(struct target *, int hartid, int regid); riscv_reg_t (*get_register)(struct target *, int hartid, int regid);
@ -95,8 +95,6 @@ typedef struct {
void (*on_resume)(struct target *target); void (*on_resume)(struct target *target);
void (*on_step)(struct target *target); void (*on_step)(struct target *target);
enum riscv_halt_reason (*halt_reason)(struct target *target); enum riscv_halt_reason (*halt_reason)(struct target *target);
void (*debug_buffer_enter)(struct target *target, struct riscv_program *program);
void (*debug_buffer_leave)(struct target *target, struct riscv_program *program);
void (*write_debug_buffer)(struct target *target, unsigned index, void (*write_debug_buffer)(struct target *target, unsigned index,
riscv_insn_t d); riscv_insn_t d);
riscv_insn_t (*read_debug_buffer)(struct target *target, unsigned index); riscv_insn_t (*read_debug_buffer)(struct target *target, unsigned index);
@ -113,6 +111,9 @@ extern int riscv_command_timeout_sec;
/* Wall-clock timeout after reset. Settable via RISC-V Target commands.*/ /* Wall-clock timeout after reset. Settable via RISC-V Target commands.*/
extern int riscv_reset_timeout_sec; extern int riscv_reset_timeout_sec;
extern bool riscv_use_scratch_ram;
extern uint64_t riscv_scratch_ram_address;
/* Everything needs the RISC-V specific info structure, so here's a nice macro /* Everything needs the RISC-V specific info structure, so here's a nice macro
* that provides that. */ * that provides that. */
static inline riscv_info_t *riscv_info(const struct target *target) __attribute__((unused)); static inline riscv_info_t *riscv_info(const struct target *target) __attribute__((unused));
@ -213,10 +214,6 @@ int riscv_count_triggers_of_hart(struct target *target, int hartid);
/* These helper functions let the generic program interface get target-specific /* These helper functions let the generic program interface get target-specific
* information. */ * information. */
size_t riscv_debug_buffer_size(struct target *target); 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);
riscv_insn_t riscv_read_debug_buffer(struct target *target, int index); riscv_insn_t riscv_read_debug_buffer(struct target *target, int index);
riscv_addr_t riscv_read_debug_buffer_x(struct target *target, int index); riscv_addr_t riscv_read_debug_buffer_x(struct target *target, int index);