This is an automated email from Gerrit. "Dietmar May <dietmar....@outlook.com>" just uploaded a new patch set to Gerrit, which you can find at https://review.openocd.org/c/openocd/+/6476
-- gerrit commit 0b98df878e42713a8d6deac48beaf62fec0e2e2e Author: Dietmar May <dietmar....@outlook.com> Date: Fri Aug 20 19:33:40 2021 -0400 target: reg cmd added sync, target name in outputs When outputting registers on a multi-core (SMP) system, it's important to know which core the displayed registers belong to. Having the core (target) name displayed along with the register name provides more intuitive output. Also, the target code only updates the cache and sets a dirty bit when writing register values, so it's important to know when displayed values have only been updated in the cache, and not in the cpu. > reg pc ca53.1:pc (/64): 0x00000000deadbeef (dirty) Also, it's painful to iterate through all registers individually to force an update of cache values. A new 'sync' flag supports marking all registers as dirty, so all will be read from the cpu, while preserving the previous 'force' behavior. > reg sync ===== Aarch64 registers (0) ca53.1:x0 (/64): 0x0000000000c56789 (1) ca53.1:x1 (/64): 0x0000000098760000 (2) ca53.1:x2 (/64): 0x0000000000000000 (3) ca53.1:x3 (/64): 0x0000000000000000 ... (29) ca53.1:x29 (/64): 0x0000000000000000 (30) ca53.1:x30 (/64): 0x00000000codeace5 (31) ca53.1:sp (/64): 0x00000000codeba11 (32) ca53.1:pc (/64): 0x00000000deadf1ea (33) ca53.1:cpsr (/32): 0x200003cd (34) ca53.1:v0 (/128): 0x00000000000000000000000000000000 ... (76) ca53.1:SPSR_EL3 (/32): 0x000001cd ===== Aarch32 registers (77) ca53.1:r0 (/32): 0x00c56789 (78) ca53.1:r1 (/32): 0x98760000 ... (126) ca53.1:fpscr (/32): 0x00000000 Signed-off-by: Dietmar May <dietmar....@outlook.com> Change-Id: I6a4e14deb39cb8fe2e1bdeebb530bb9e9292f4e4 diff --git a/src/target/target.c b/src/target/target.c index 7bace83f9..8ad9e6a19 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -3076,6 +3076,17 @@ COMMAND_HANDLER(handle_reg_command) struct target *target = get_current_target(CMD_CTX); struct reg *reg = NULL; + int force = 0; + + if (CMD_ARGC > 0) { + if (strcmp(CMD_ARGV[CMD_ARGC-1], "force") == 0) { + force = 1; + --CMD_ARGC; + } else if (strcmp(CMD_ARGV[CMD_ARGC-1], "sync") == 0) { + force = 2; + --CMD_ARGC; + } + } /* list all available registers for the current target */ if (CMD_ARGC == 0) { @@ -3092,21 +3103,31 @@ COMMAND_HANDLER(handle_reg_command) i++, reg++, count++) { if (reg->exist == false || reg->hidden) continue; + + /* keep old force behavior - only read reg if sync */ + if (force == 2) { + int retval = reg->type->get(reg); + if (retval != ERROR_OK) { + LOG_ERROR("Could not read register '%s'", reg->name); + return retval; + } + } + /* only print cached values if they are valid */ if (reg->valid) { char *value = buf_to_hex_str(reg->value, reg->size); command_print(CMD, - "(%i) %s (/%" PRIu32 "): 0x%s%s", - count, reg->name, + "(%i) %s:%s (/%" PRIu32 "): 0x%s%s", + count, target->cmd_name, reg->name, reg->size, value, reg->dirty ? " (dirty)" : ""); free(value); } else { - command_print(CMD, "(%i) %s (/%" PRIu32 ")", - count, reg->name, + command_print(CMD, "(%i) %s:%s (/%" PRIu32 ")", + count, target->cmd_name, reg->name, reg->size); } } @@ -3116,6 +3137,12 @@ COMMAND_HANDLER(handle_reg_command) return ERROR_OK; } + /* handle sync request - mark all registers as invalid */ + if (force == 2 && CMD_ARGC == 0) { + register_cache_invalidate(target->reg_cache); + return ERROR_OK; + } + /* access a single register by its ordinal number */ if ((CMD_ARGV[0][0] >= '0') && (CMD_ARGV[0][0] <= '9')) { unsigned num; @@ -3137,8 +3164,9 @@ COMMAND_HANDLER(handle_reg_command) } if (!reg) { - command_print(CMD, "%i is out of bounds, the current target " - "has only %i registers (0 - %i)", num, count, count - 1); + command_print(CMD, "%i is out of bounds, the current target %s" + "has only %i registers (0 - %i)", num, target->cmd_name, + count, count - 1); return ERROR_OK; } } else { @@ -3157,7 +3185,7 @@ COMMAND_HANDLER(handle_reg_command) /* display a register */ if ((CMD_ARGC == 1) || ((CMD_ARGC == 2) && !((CMD_ARGV[1][0] >= '0') && (CMD_ARGV[1][0] <= '9')))) { - if ((CMD_ARGC == 2) && (strcmp(CMD_ARGV[1], "force") == 0)) + if (force == 1) reg->valid = 0; if (reg->valid == 0) { @@ -3168,7 +3196,8 @@ COMMAND_HANDLER(handle_reg_command) } } char *value = buf_to_hex_str(reg->value, reg->size); - command_print(CMD, "%s (/%i): 0x%s", reg->name, (int)(reg->size), value); + command_print(CMD, "%s:%s (/%i): 0x%s%s", target->cmd_name, reg->name, + (int)(reg->size), value, reg->dirty ? " (dirty)" : ""); free(value); return ERROR_OK; } @@ -3185,7 +3214,8 @@ COMMAND_HANDLER(handle_reg_command) LOG_ERROR("Could not write to register '%s'", reg->name); } else { char *value = buf_to_hex_str(reg->value, reg->size); - command_print(CMD, "%s (/%i): 0x%s", reg->name, (int)(reg->size), value); + command_print(CMD, "%s:%s (/%i): 0x%s", target->cmd_name, reg->name, + (int)(reg->size), value); free(value); } @@ -3201,6 +3231,11 @@ not_found: return ERROR_OK; } +__COMMAND_HANDLER(target_handle_reg_command) +{ + return CALL_COMMAND_HANDLER(handle_reg_command); +} + COMMAND_HANDLER(handle_poll_command) { int retval = ERROR_OK; @@ -6522,8 +6557,9 @@ static const struct command_registration target_exec_command_handlers[] = { .handler = handle_reg_command, .mode = COMMAND_EXEC, .help = "display (reread from target with \"force\") or set a register; " - "with no arguments, displays all registers and their values", - .usage = "[(register_number|register_name) [(value|'force')]]", + "with no arguments, displays all registers and their values, " + "with sync flags all registers as dirty", + .usage = "[(register_number|register_name) [(value|'force')] | sync]", }, { .name = "poll", --