diff --git a/src/flash/nor/stm32lx.c b/src/flash/nor/stm32lx.c index 488dc978a..585914de2 100644 --- a/src/flash/nor/stm32lx.c +++ b/src/flash/nor/stm32lx.c @@ -884,11 +884,10 @@ static int stm32lx_get_info(struct flash_bank *bank, struct command_invocation * if (rev_id == info->revs[i].rev) rev_str = info->revs[i].str; - if (rev_str) { + if (rev_str) command_print_sameline(cmd, "%s - Rev: %s", info->device_str, rev_str); - } else { + else command_print_sameline(cmd, "%s - Rev: unknown (0x%04x)", info->device_str, rev_id); - } return ERROR_OK; } diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 75d1f80b0..eb380cb08 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -57,7 +57,6 @@ static void riscv013_fill_dmi_write_u64(struct target *target, char *buf, int a, static void riscv013_fill_dmi_read_u64(struct target *target, char *buf, int a); static int riscv013_dmi_write_u64_bits(struct target *target); static void riscv013_fill_dmi_nop_u64(struct target *target, char *buf); -static int register_read(struct target *target, uint64_t *value, uint32_t number); static int register_read_direct(struct target *target, uint64_t *value, uint32_t number); static int register_write_direct(struct target *target, unsigned number, uint64_t value); @@ -1022,8 +1021,7 @@ static int examine_progbuf(struct target *target) return ERROR_OK; } - uint64_t s0; - if (register_read(target, &s0, GDB_REGNO_S0) != ERROR_OK) + if (riscv_save_register(target, GDB_REGNO_S0) != ERROR_OK) return ERROR_FAIL; struct riscv_program program; @@ -1039,9 +1037,6 @@ static int examine_progbuf(struct target *target) riscv_program_insert(&program, sw(S0, S0, 0)); int result = riscv_program_exec(&program, target); - if (register_write_direct(target, GDB_REGNO_S0, s0) != ERROR_OK) - return ERROR_FAIL; - if (result != ERROR_OK) { /* This program might have failed if the program buffer is not * writable. */ @@ -1089,7 +1084,7 @@ static int prep_for_register_access(struct target *target, uint64_t *mstatus, int regno) { if (is_fpu_reg(regno) || is_vector_reg(regno)) { - if (register_read(target, mstatus, GDB_REGNO_MSTATUS) != ERROR_OK) + if (register_read_direct(target, mstatus, GDB_REGNO_MSTATUS) != ERROR_OK) return ERROR_FAIL; if (is_fpu_reg(regno) && (*mstatus & MSTATUS_FS) == 0) { if (register_write_direct(target, GDB_REGNO_MSTATUS, @@ -1315,8 +1310,7 @@ static int register_write_direct(struct target *target, unsigned number, struct riscv_program program; riscv_program_init(&program, target); - uint64_t s0; - if (register_read(target, &s0, GDB_REGNO_S0) != ERROR_OK) + if (riscv_save_register(target, GDB_REGNO_S0) != ERROR_OK) return ERROR_FAIL; uint64_t mstatus; @@ -1352,9 +1346,6 @@ static int register_write_direct(struct target *target, unsigned number, riscv_program_insert(&program, vsetvli(ZERO, S0, value)); } else { - if (register_write_direct(target, GDB_REGNO_S0, value) != ERROR_OK) - return ERROR_FAIL; - if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) { if (riscv_supports_extension(target, 'D')) riscv_program_insert(&program, fmv_d_x(number - GDB_REGNO_FPR0, S0)); @@ -1365,7 +1356,7 @@ static int register_write_direct(struct target *target, unsigned number, * vsetvli and vsetvl instructions, and the fault-only-rst vector * load instruction variants." */ riscv_reg_t vtype; - if (register_read(target, &vtype, GDB_REGNO_VTYPE) != ERROR_OK) + if (register_read_direct(target, &vtype, GDB_REGNO_VTYPE) != ERROR_OK) return ERROR_FAIL; if (riscv_program_insert(&program, vsetvli(ZERO, S0, vtype)) != ERROR_OK) return ERROR_FAIL; @@ -1375,6 +1366,8 @@ static int register_write_direct(struct target *target, unsigned number, LOG_ERROR("Unsupported register (enum gdb_regno)(%d)", number); return ERROR_FAIL; } + if (register_write_direct(target, GDB_REGNO_S0, value) != ERROR_OK) + return ERROR_FAIL; } int exec_out = riscv_program_exec(&program, target); @@ -1390,30 +1383,9 @@ static int register_write_direct(struct target *target, unsigned number, if (cleanup_after_register_access(target, mstatus, number) != ERROR_OK) return ERROR_FAIL; - /* Restore S0. */ - if (register_write_direct(target, GDB_REGNO_S0, s0) != ERROR_OK) - return ERROR_FAIL; - return exec_out; } -/** Read register value from the target. Also update the cached value. */ -static int register_read(struct target *target, uint64_t *value, uint32_t number) -{ - if (number == GDB_REGNO_ZERO) { - *value = 0; - return ERROR_OK; - } - int result = register_read_direct(target, value, number); - if (result != ERROR_OK) - return ERROR_FAIL; - if (target->reg_cache) { - struct reg *reg = &target->reg_cache->reg_list[number]; - buf_set_u64(reg->value, 0, reg->size, *value); - } - return ERROR_OK; -} - /** Actually read registers from the target right now. */ static int register_read_direct(struct target *target, uint64_t *value, uint32_t number) { @@ -1429,8 +1401,7 @@ static int register_read_direct(struct target *target, uint64_t *value, uint32_t scratch_mem_t scratch; bool use_scratch = false; - riscv_reg_t s0; - if (register_read(target, &s0, GDB_REGNO_S0) != ERROR_OK) + if (riscv_save_register(target, GDB_REGNO_S0) != ERROR_OK) return ERROR_FAIL; /* Write program to move data into s0. */ @@ -1485,10 +1456,6 @@ static int register_read_direct(struct target *target, uint64_t *value, uint32_t if (cleanup_after_register_access(target, mstatus, number) != ERROR_OK) return ERROR_FAIL; - - /* Restore S0. */ - if (register_write_direct(target, GDB_REGNO_S0, s0) != ERROR_OK) - return ERROR_FAIL; } if (result == ERROR_OK) { @@ -1550,7 +1517,7 @@ static int discover_vlenb(struct target *target) RISCV_INFO(r); riscv_reg_t vlenb; - if (register_read(target, &vlenb, GDB_REGNO_VLENB) != ERROR_OK) { + if (register_read_direct(target, &vlenb, GDB_REGNO_VLENB) != ERROR_OK) { LOG_WARNING("Couldn't read vlenb for %s; vector register access won't work.", target_name(target)); r->vlenb = 0; @@ -1737,7 +1704,19 @@ static int examine(struct target *target) else r->xlen = 32; - if (register_read(target, &r->misa, GDB_REGNO_MISA)) { + /* Save s0 and s1. The register cache hasn't be initialized yet so we + * need to take care of this manually. */ + uint64_t s0, s1; + if (register_read_direct(target, &s0, GDB_REGNO_S0) != ERROR_OK) { + LOG_ERROR("Fatal: Failed to read s0 from hart %d.", r->current_hartid); + return ERROR_FAIL; + } + if (register_read_direct(target, &s1, GDB_REGNO_S1) != ERROR_OK) { + LOG_ERROR("Fatal: Failed to read s1 from hart %d.", r->current_hartid); + return ERROR_FAIL; + } + + if (register_read_direct(target, &r->misa, GDB_REGNO_MISA)) { LOG_ERROR("Fatal: Failed to read MISA from hart %d.", r->current_hartid); return ERROR_FAIL; } @@ -1756,6 +1735,16 @@ static int examine(struct target *target) LOG_DEBUG(" hart %d: XLEN=%d, misa=0x%" PRIx64, r->current_hartid, r->xlen, r->misa); + /* Restore s0 and s1. */ + if (register_write_direct(target, GDB_REGNO_S0, s0) != ERROR_OK) { + LOG_ERROR("Fatal: Failed to write s0 back to hart %d.", r->current_hartid); + return ERROR_FAIL; + } + if (register_write_direct(target, GDB_REGNO_S1, s1) != ERROR_OK) { + LOG_ERROR("Fatal: Failed to write s1 back to hart %d.", r->current_hartid); + return ERROR_FAIL; + } + if (!halted) riscv013_step_or_resume_current_hart(target, false, false); @@ -1927,9 +1916,9 @@ static int prep_for_vector_access(struct target *target, uint64_t *vtype, } /* Save vtype and vl. */ - if (register_read(target, vtype, GDB_REGNO_VTYPE) != ERROR_OK) + if (register_read_direct(target, vtype, GDB_REGNO_VTYPE) != ERROR_OK) return ERROR_FAIL; - if (register_read(target, vl, GDB_REGNO_VL) != ERROR_OK) + if (register_read_direct(target, vl, GDB_REGNO_VL) != ERROR_OK) return ERROR_FAIL; if (register_write_direct(target, GDB_REGNO_VTYPE, encoded_vsew << 3) != ERROR_OK) @@ -1960,8 +1949,7 @@ static int riscv013_get_register_buf(struct target *target, if (riscv_select_current_hart(target) != ERROR_OK) return ERROR_FAIL; - riscv_reg_t s0; - if (register_read(target, &s0, GDB_REGNO_S0) != ERROR_OK) + if (riscv_save_register(target, GDB_REGNO_S0) != ERROR_OK) return ERROR_FAIL; uint64_t mstatus; @@ -2005,8 +1993,6 @@ static int riscv013_get_register_buf(struct target *target, if (cleanup_after_register_access(target, mstatus, regno) != ERROR_OK) return ERROR_FAIL; - if (register_write_direct(target, GDB_REGNO_S0, s0) != ERROR_OK) - return ERROR_FAIL; return result; } @@ -2019,8 +2005,7 @@ static int riscv013_set_register_buf(struct target *target, if (riscv_select_current_hart(target) != ERROR_OK) return ERROR_FAIL; - riscv_reg_t s0; - if (register_read(target, &s0, GDB_REGNO_S0) != ERROR_OK) + if (riscv_save_register(target, GDB_REGNO_S0) != ERROR_OK) return ERROR_FAIL; uint64_t mstatus; @@ -2053,8 +2038,6 @@ static int riscv013_set_register_buf(struct target *target, if (cleanup_after_register_access(target, mstatus, regno) != ERROR_OK) return ERROR_FAIL; - if (register_write_direct(target, GDB_REGNO_S0, s0) != ERROR_OK) - return ERROR_FAIL; return result; } @@ -2562,11 +2545,11 @@ static int modify_privilege(struct target *target, uint64_t *mstatus, uint64_t * if (riscv_enable_virtual && has_sufficient_progbuf(target, 5)) { /* Read DCSR */ uint64_t dcsr; - if (register_read(target, &dcsr, GDB_REGNO_DCSR) != ERROR_OK) + if (register_read_direct(target, &dcsr, GDB_REGNO_DCSR) != ERROR_OK) return ERROR_FAIL; /* Read and save MSTATUS */ - if (register_read(target, mstatus, GDB_REGNO_MSTATUS) != ERROR_OK) + if (register_read_direct(target, mstatus, GDB_REGNO_MSTATUS) != ERROR_OK) return ERROR_FAIL; *mstatus_old = *mstatus; @@ -3349,10 +3332,9 @@ static int read_memory_progbuf_one(struct target *target, target_addr_t address, if (modify_privilege(target, &mstatus, &mstatus_old) != ERROR_OK) return ERROR_FAIL; - uint64_t s0; int result = ERROR_FAIL; - if (register_read(target, &s0, GDB_REGNO_S0) != ERROR_OK) + if (riscv_save_register(target, GDB_REGNO_S0) != ERROR_OK) goto restore_mstatus; /* Write the program (load, increment) */ @@ -3392,19 +3374,15 @@ static int read_memory_progbuf_one(struct target *target, target_addr_t address, riscv_xlen(target), AC_ACCESS_REGISTER_WRITE | AC_ACCESS_REGISTER_TRANSFER | AC_ACCESS_REGISTER_POSTEXEC); if (execute_abstract_command(target, command) != ERROR_OK) - goto restore_s0; + goto restore_mstatus; uint64_t value; - if (register_read(target, &value, GDB_REGNO_S0) != ERROR_OK) - goto restore_s0; + if (register_read_direct(target, &value, GDB_REGNO_S0) != ERROR_OK) + goto restore_mstatus; buf_set_u64(buffer, 0, 8 * size, value); log_memory_access(address, value, size, true); result = ERROR_OK; -restore_s0: - if (riscv_set_register(target, GDB_REGNO_S0, s0) != ERROR_OK) - result = ERROR_FAIL; - restore_mstatus: if (mstatus != mstatus_old) if (register_write_direct(target, GDB_REGNO_MSTATUS, mstatus_old)) @@ -3449,12 +3427,11 @@ static int read_memory_progbuf(struct target *target, target_addr_t address, * s1 holds the next data value read * s2 is a counter in case increment is 0 */ - uint64_t s0, s1, s2; - if (register_read(target, &s0, GDB_REGNO_S0) != ERROR_OK) + if (riscv_save_register(target, GDB_REGNO_S0) != ERROR_OK) return ERROR_FAIL; - if (register_read(target, &s1, GDB_REGNO_S1) != ERROR_OK) + if (riscv_save_register(target, GDB_REGNO_S1) != ERROR_OK) return ERROR_FAIL; - if (increment == 0 && register_read(target, &s2, GDB_REGNO_S2) != ERROR_OK) + if (increment == 0 && riscv_save_register(target, GDB_REGNO_S2) != ERROR_OK) return ERROR_FAIL; /* Write the program (load, increment) */ @@ -3519,11 +3496,6 @@ static int read_memory_progbuf(struct target *target, target_addr_t address, result = ERROR_OK; } - riscv_set_register(target, GDB_REGNO_S0, s0); - riscv_set_register(target, GDB_REGNO_S1, s1); - if (increment == 0) - riscv_set_register(target, GDB_REGNO_S2, s2); - /* Restore MSTATUS */ if (mstatus != mstatus_old) if (register_write_direct(target, GDB_REGNO_MSTATUS, mstatus_old)) @@ -3814,10 +3786,9 @@ static int write_memory_progbuf(struct target *target, target_addr_t address, */ int result = ERROR_OK; - uint64_t s0, s1; - if (register_read(target, &s0, GDB_REGNO_S0) != ERROR_OK) + if (riscv_save_register(target, GDB_REGNO_S0) != ERROR_OK) return ERROR_FAIL; - if (register_read(target, &s1, GDB_REGNO_S1) != ERROR_OK) + if (riscv_save_register(target, GDB_REGNO_S1) != ERROR_OK) return ERROR_FAIL; /* Write the program (store, increment) */ @@ -3965,11 +3936,6 @@ static int write_memory_progbuf(struct target *target, target_addr_t address, error: dmi_write(target, DM_ABSTRACTAUTO, 0); - if (register_write_direct(target, GDB_REGNO_S1, s1) != ERROR_OK) - return ERROR_FAIL; - if (register_write_direct(target, GDB_REGNO_S0, s0) != ERROR_OK) - return ERROR_FAIL; - /* Restore MSTATUS */ if (mstatus != mstatus_old) if (register_write_direct(target, GDB_REGNO_MSTATUS, mstatus_old)) @@ -4079,16 +4045,16 @@ static int riscv013_get_register(struct target *target, int result = ERROR_OK; if (rid == GDB_REGNO_PC) { /* TODO: move this into riscv.c. */ - result = register_read(target, value, GDB_REGNO_DPC); + result = register_read_direct(target, value, GDB_REGNO_DPC); LOG_DEBUG("[%d] read PC from DPC: 0x%" PRIx64, target->coreid, *value); } else if (rid == GDB_REGNO_PRIV) { uint64_t dcsr; /* TODO: move this into riscv.c. */ - result = register_read(target, &dcsr, GDB_REGNO_DCSR); + result = register_read_direct(target, &dcsr, GDB_REGNO_DCSR); *value = set_field(0, VIRT_PRIV_V, get_field(dcsr, CSR_DCSR_V)); *value = set_field(*value, VIRT_PRIV_PRV, get_field(dcsr, CSR_DCSR_PRV)); } else { - result = register_read(target, value, rid); + result = register_read_direct(target, value, rid); if (result != ERROR_OK) *value = -1; } @@ -4117,7 +4083,7 @@ static int riscv013_set_register(struct target *target, int rid, uint64_t value) } } else if (rid == GDB_REGNO_PRIV) { uint64_t dcsr; - register_read(target, &dcsr, GDB_REGNO_DCSR); + register_read_direct(target, &dcsr, GDB_REGNO_DCSR); dcsr = set_field(dcsr, CSR_DCSR_PRV, get_field(value, VIRT_PRIV_PRV)); dcsr = set_field(dcsr, CSR_DCSR_V, get_field(value, VIRT_PRIV_V)); return register_write_direct(target, GDB_REGNO_DCSR, dcsr); @@ -4319,7 +4285,7 @@ static bool riscv013_is_halted(struct target *target) static enum riscv_halt_reason riscv013_halt_reason(struct target *target) { riscv_reg_t dcsr; - int result = register_read(target, &dcsr, GDB_REGNO_DCSR); + int result = register_read_direct(target, &dcsr, GDB_REGNO_DCSR); if (result != ERROR_OK) return RISCV_HALT_UNKNOWN; @@ -4779,14 +4745,18 @@ static int riscv013_on_step_or_resume(struct target *target, bool step) /* We want to twiddle some bits in the debug CSR so debugging works. */ riscv_reg_t dcsr; - int result = register_read(target, &dcsr, GDB_REGNO_DCSR); + int result = register_read_direct(target, &dcsr, GDB_REGNO_DCSR); if (result != ERROR_OK) return result; dcsr = set_field(dcsr, CSR_DCSR_STEP, step); dcsr = set_field(dcsr, CSR_DCSR_EBREAKM, riscv_ebreakm); dcsr = set_field(dcsr, CSR_DCSR_EBREAKS, riscv_ebreaks); dcsr = set_field(dcsr, CSR_DCSR_EBREAKU, riscv_ebreaku); - return riscv_set_register(target, GDB_REGNO_DCSR, dcsr); + if (riscv_set_register(target, GDB_REGNO_DCSR, dcsr) != ERROR_OK) + return ERROR_FAIL; + if (riscv_flush_registers(target) != ERROR_OK) + return ERROR_FAIL; + return ERROR_OK; } static int riscv013_step_or_resume_current_hart(struct target *target, @@ -4799,6 +4769,9 @@ static int riscv013_step_or_resume_current_hart(struct target *target, return ERROR_FAIL; } + if (riscv_flush_registers(target) != ERROR_OK) + return ERROR_FAIL; + /* Issue the resume command, and then wait for the current hart to resume. */ uint32_t dmcontrol = DM_DMCONTROL_DMACTIVE | DM_DMCONTROL_RESUMEREQ; if (use_hasel) diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index 00405e94b..40a897284 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -1155,6 +1155,29 @@ int riscv_select_current_hart(struct target *target) return riscv_set_current_hartid(target, target->coreid); } +int riscv_flush_registers(struct target *target) +{ + RISCV_INFO(r); + + if (!target->reg_cache) + return ERROR_OK; + + for (uint32_t number = 0; number < target->reg_cache->num_regs; number++) { + struct reg *reg = &target->reg_cache->reg_list[number]; + if (reg->valid && reg->dirty) { + uint64_t value = buf_get_u64(reg->value, 0, reg->size); + LOG_DEBUG("[%s] %s is dirty; write back 0x%" PRIx64, + target_name(target), reg->name, value); + int result = r->set_register(target, number, value); + if (result != ERROR_OK) + return ERROR_FAIL; + reg->dirty = false; + } + } + + return ERROR_OK; +} + int halt_prep(struct target *target) { RISCV_INFO(r); @@ -1276,27 +1299,6 @@ static int riscv_deassert_reset(struct target *target) return tt->deassert_reset(target); } -int riscv_resume_prep_all_harts(struct target *target) -{ - RISCV_INFO(r); - - LOG_DEBUG("[%s] prep hart", target_name(target)); - if (riscv_select_current_hart(target) != ERROR_OK) - return ERROR_FAIL; - if (riscv_is_halted(target)) { - if (r->resume_prep(target) != ERROR_OK) - return ERROR_FAIL; - } else { - LOG_DEBUG("[%s] hart requested resume, but was already resumed", - target_name(target)); - } - - LOG_DEBUG("[%s] mark as prepped", target_name(target)); - r->prepped = true; - - return ERROR_OK; -} - /* state must be riscv_reg_t state[RISCV_MAX_HWBPS] = {0}; */ static int disable_triggers(struct target *target, riscv_reg_t *state) { @@ -1411,7 +1413,9 @@ static int resume_prep(struct target *target, int current, } if (r->is_halted) { - if (riscv_resume_prep_all_harts(target) != ERROR_OK) + if (riscv_select_current_hart(target) != ERROR_OK) + return ERROR_FAIL; + if (r->resume_prep(target) != ERROR_OK) return ERROR_FAIL; } @@ -3439,11 +3443,9 @@ int riscv_step_rtos_hart(struct target *target) LOG_ERROR("Hart isn't halted before single step!"); return ERROR_FAIL; } - riscv_invalidate_register_cache(target); r->on_step(target); if (r->step_current_hart(target) != ERROR_OK) return ERROR_FAIL; - riscv_invalidate_register_cache(target); r->on_halt(target); if (!riscv_is_halted(target)) { LOG_ERROR("Hart was not halted after single step!"); @@ -3585,14 +3587,17 @@ int riscv_set_register(struct target *target, enum gdb_regno regid, riscv_reg_t struct reg *reg = &target->reg_cache->reg_list[regid]; buf_set_u64(reg->value, 0, reg->size, value); - int result = r->set_register(target, regid, value); - if (result == ERROR_OK) - reg->valid = gdb_regno_cacheable(regid, true); - else - reg->valid = false; + if (gdb_regno_cacheable(regid, true)) { + reg->valid = true; + reg->dirty = true; + } else { + if (r->set_register(target, regid, value) != ERROR_OK) + return ERROR_FAIL; + } + LOG_DEBUG("[%s] wrote 0x%" PRIx64 " to %s valid=%d", target_name(target), value, reg->name, reg->valid); - return result; + return ERROR_OK; } int riscv_get_register(struct target *target, riscv_reg_t *value, @@ -3600,8 +3605,6 @@ int riscv_get_register(struct target *target, riscv_reg_t *value, { RISCV_INFO(r); - keep_alive(); - struct reg *reg = &target->reg_cache->reg_list[regid]; if (!reg->exist) { LOG_DEBUG("[%s] %s does not exist.", @@ -3625,14 +3628,40 @@ int riscv_get_register(struct target *target, riscv_reg_t *value, int result = r->get_register(target, value, regid); - if (result == ERROR_OK) + if (result == ERROR_OK) { + /* Update the cache in case we're called from + * riscv_save_register(). */ + buf_set_u64(reg->value, 0, reg->size, *value); reg->valid = gdb_regno_cacheable(regid, false); + } LOG_DEBUG("[%s] %s: %" PRIx64, target_name(target), gdb_regno_name(regid), *value); return result; } +int riscv_save_register(struct target *target, enum gdb_regno regid) +{ + riscv_reg_t value; + if (!target->reg_cache) { + assert(!target_was_examined(target)); + return ERROR_OK; + } + + struct reg *reg = &target->reg_cache->reg_list[regid]; + LOG_DEBUG("[%s] save %s", target_name(target), reg->name); + if (riscv_get_register(target, &value, regid) != ERROR_OK) + return ERROR_FAIL; + + if (!reg->valid) + return ERROR_FAIL; + /* Mark the register dirty. We assume that this function is called + * because the caller is about to mess with the underlying value of the + * register. */ + reg->dirty = true; + return ERROR_OK; +} + bool riscv_is_halted(struct target *target) { RISCV_INFO(r); diff --git a/src/target/riscv/riscv.h b/src/target/riscv/riscv.h index 5e057e712..3a80c78eb 100644 --- a/src/target/riscv/riscv.h +++ b/src/target/riscv/riscv.h @@ -350,6 +350,11 @@ int riscv_set_register(struct target *target, enum gdb_regno i, riscv_reg_t v); /** Get register, from the cache if it's in there. */ int riscv_get_register(struct target *target, riscv_reg_t *value, enum gdb_regno r); +/** Read the register into the cache, and mark it dirty so it will be restored + * before resuming. */ +int riscv_save_register(struct target *target, enum gdb_regno regid); +/** Write all dirty registers to the target. */ +int riscv_flush_registers(struct target *target); /* Checks the state of the current hart -- "is_halted" checks the actual * on-device register. */