diff options
author | Tim Newsome <tim@sifive.com> | 2019-07-15 10:34:40 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-07-15 10:34:40 -0700 |
commit | 09016bcb6e7c3a8246a80189a76babf2827ec198 (patch) | |
tree | b5f97b0804414fdc361104c6bae4683c0f111a12 | |
parent | 9b34f8ca3c7b20131cb59cc2347cd88b4f2cb7fe (diff) | |
download | riscv-openocd-09016bcb6e7c3a8246a80189a76babf2827ec198.zip riscv-openocd-09016bcb6e7c3a8246a80189a76babf2827ec198.tar.gz riscv-openocd-09016bcb6e7c3a8246a80189a76babf2827ec198.tar.bz2 |
Optimize reading a single byte/short/word. (#390)
gdb has developed a nasty habit of very often reading 30-some
half-words. This change speeds that up significantly.
Change-Id: Iab1b7575bec5c57051c6e630ae292dddf8fe6350
-rw-r--r-- | src/target/riscv/riscv-013.c | 65 |
1 files changed, 61 insertions, 4 deletions
diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 47c1c86..cfa9291 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -2456,6 +2456,59 @@ error: return result; } +/* Only need to save/restore one GPR to read a single word, and the progbuf + * program doesn't need to increment. */ +static int read_memory_progbuf_one(struct target *target, target_addr_t address, + uint32_t size, uint8_t *buffer) +{ + uint64_t s0; + + if (register_read(target, &s0, GDB_REGNO_S0) != ERROR_OK) + return ERROR_FAIL; + + /* Write the program (load, increment) */ + struct riscv_program program; + riscv_program_init(&program, target); + switch (size) { + case 1: + riscv_program_lbr(&program, GDB_REGNO_S0, GDB_REGNO_S0, 0); + break; + case 2: + riscv_program_lhr(&program, GDB_REGNO_S0, GDB_REGNO_S0, 0); + break; + case 4: + riscv_program_lwr(&program, GDB_REGNO_S0, GDB_REGNO_S0, 0); + break; + default: + LOG_ERROR("Unsupported size: %d", size); + return ERROR_FAIL; + } + + if (riscv_program_ebreak(&program) != ERROR_OK) + return ERROR_FAIL; + if (riscv_program_write(&program) != ERROR_OK) + return ERROR_FAIL; + + /* Write address to S0, and execute buffer. */ + if (write_abstract_arg(target, 0, address, riscv_xlen(target)) != ERROR_OK) + return ERROR_FAIL; + uint32_t command = access_register_command(target, GDB_REGNO_S0, + riscv_xlen(target), AC_ACCESS_REGISTER_WRITE | + AC_ACCESS_REGISTER_TRANSFER | AC_ACCESS_REGISTER_POSTEXEC); + if (execute_abstract_command(target, command) != ERROR_OK) + return ERROR_FAIL; + + uint64_t value; + if (register_read(target, &value, GDB_REGNO_S0) != ERROR_OK) + return ERROR_FAIL; + write_to_buf(buffer, value, size); + + if (riscv_set_register(target, GDB_REGNO_S0, s0) != ERROR_OK) + return ERROR_FAIL; + + return ERROR_OK; +} + /** * Read the requested memory, silently handling memory access errors. */ @@ -2471,6 +2524,12 @@ static int read_memory_progbuf(struct target *target, target_addr_t address, memset(buffer, 0, count*size); + if (execute_fence(target) != ERROR_OK) + return ERROR_FAIL; + + if (count == 1) + return read_memory_progbuf_one(target, address, size, buffer); + /* s0 holds the next address to write to * s1 holds the next data value to write */ @@ -2480,9 +2539,6 @@ static int read_memory_progbuf(struct target *target, target_addr_t address, if (register_read(target, &s1, GDB_REGNO_S1) != ERROR_OK) return ERROR_FAIL; - if (execute_fence(target) != ERROR_OK) - return ERROR_FAIL; - /* Write the program (load, increment) */ struct riscv_program program; riscv_program_init(&program, target); @@ -2504,7 +2560,8 @@ static int read_memory_progbuf(struct target *target, target_addr_t address, if (riscv_program_ebreak(&program) != ERROR_OK) return ERROR_FAIL; - riscv_program_write(&program); + if (riscv_program_write(&program) != ERROR_OK) + return ERROR_FAIL; result = read_memory_progbuf_inner(target, address, size, count, buffer); |