Files
openocd/src/target/riscv/debug_reg_printer.c
Bernhard Rosenkränzer 56141bb349 target: riscv: Drop new typedefs added by the updated riscv-debug-spec files
The advantage of this patch is that it brings the new code closer to
OpenOCD coding style - the disadvantage is that it involves modifying
autogenerated files, making it harder to drop in new versions when
riscv-debug-spec changes.

Change-Id: I4c317e11ab1652333b0bb44168f953ef452d3ef5
Signed-off-by: Bernhard Rosenkränzer <bero@baylibre.com>
Reviewed-on: https://review.openocd.org/c/openocd/+/8896
Reviewed-by: Evgeniy Naydanov <evgeniy.naydanov@syntacore.com>
Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
Tested-by: jenkins
2025-11-12 20:16:13 +00:00

110 lines
3.3 KiB
C

// SPDX-License-Identifier: GPL-2.0-or-later
#include <stdio.h>
#include <inttypes.h>
#include <assert.h>
#include <stdarg.h>
#include "debug_reg_printer.h"
static unsigned int get_len_or_sprintf(char *buf, unsigned int curr, const char *format, ...)
{
assert(format);
va_list args;
int length;
va_start(args, format);
if (buf)
length = vsprintf(buf + curr, format, args);
else
length = vsnprintf(NULL, 0, format, args);
va_end(args);
assert(length >= 0);
return (unsigned int)length;
}
static unsigned int print_number(char *buf, unsigned int offset, uint64_t value)
{
const char * const format = value > 9 ? "0x%" PRIx64 : "%" PRIx64;
return get_len_or_sprintf(buf, offset, format, value);
}
static unsigned int riscv_debug_reg_field_value_to_s(char *buf, unsigned int offset,
const char * const *field_value_names, uint64_t field_value)
{
const char * const field_value_name = field_value_names ?
field_value_names[field_value] :
NULL;
if (!field_value_name)
return print_number(buf, offset, field_value);
return get_len_or_sprintf(buf, offset, "%s", field_value_name);
}
static unsigned int riscv_debug_reg_field_to_s(char *buf, unsigned int offset,
struct riscv_debug_reg_field_info field, struct riscv_debug_reg_ctx context,
uint64_t field_value)
{
const unsigned int name_len = get_len_or_sprintf(buf, offset, "%s=", field.name);
return name_len + riscv_debug_reg_field_value_to_s(buf, offset + name_len,
field.values, field_value);
}
static uint64_t riscv_debug_reg_field_value(struct riscv_debug_reg_field_info field, uint64_t value)
{
assert(field.msb < 64);
assert(field.msb >= field.lsb);
const uint64_t trailing_ones_mask = (uint64_t)(-1) >> (63 - field.msb);
return (value & trailing_ones_mask) >> field.lsb;
}
static unsigned int riscv_debug_reg_fields_to_s(char *buf, unsigned int offset,
struct riscv_debug_reg_field_list (*get_next)(struct riscv_debug_reg_ctx contex),
struct riscv_debug_reg_ctx context, uint64_t value,
enum riscv_debug_reg_show show)
{
unsigned int curr = offset;
curr += get_len_or_sprintf(buf, curr, " {");
char *separator = "";
for (struct riscv_debug_reg_field_list list; get_next; get_next = list.get_next) {
list = get_next(context);
uint64_t field_value = riscv_debug_reg_field_value(list.field, value);
if (show == RISCV_DEBUG_REG_SHOW_ALL ||
(show == RISCV_DEBUG_REG_HIDE_UNNAMED_0 &&
(field_value != 0 ||
(list.field.values && list.field.values[0]))) ||
(show == RISCV_DEBUG_REG_HIDE_ALL_0 && field_value != 0)) {
curr += get_len_or_sprintf(buf, curr, separator);
curr += riscv_debug_reg_field_to_s(buf, curr, list.field, context,
field_value);
separator = " ";
}
}
curr += get_len_or_sprintf(buf, curr, "}");
return curr - offset;
}
unsigned int riscv_debug_reg_to_s(char *buf, enum riscv_debug_reg_ordinal reg_ordinal,
struct riscv_debug_reg_ctx context, uint64_t value,
enum riscv_debug_reg_show show)
{
unsigned int length = 0;
struct riscv_debug_reg_info reg = get_riscv_debug_reg_info(reg_ordinal);
length += get_len_or_sprintf(buf, length, "%s=", reg.name);
length += print_number(buf, length, value);
if (reg.get_fields_head)
length += riscv_debug_reg_fields_to_s(buf, length,
reg.get_fields_head, context, value, show);
if (buf)
buf[length] = '\0';
return length;
}