OpenOCD
debug_reg_printer.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 
3 #include <stdio.h>
4 #include <inttypes.h>
5 #include <assert.h>
6 #include <stdarg.h>
7 
8 #include "debug_reg_printer.h"
9 
10 static unsigned int get_len_or_sprintf(char *buf, unsigned int curr, const char *format, ...)
11 {
12  assert(format);
13  va_list args;
14  int length;
15 
16  va_start(args, format);
17  if (buf)
18  length = vsprintf(buf + curr, format, args);
19  else
20  length = vsnprintf(NULL, 0, format, args);
21  va_end(args);
22  assert(length >= 0);
23  return (unsigned int)length;
24 }
25 
26 static unsigned int print_number(char *buf, unsigned int offset, uint64_t value)
27 {
28  const char * const format = value > 9 ? "0x%" PRIx64 : "%" PRIx64;
29 
30  return get_len_or_sprintf(buf, offset, format, value);
31 }
32 
33 static unsigned int riscv_debug_reg_field_value_to_s(char *buf, unsigned int offset,
34  const char * const *field_value_names, uint64_t field_value)
35 {
36  const char * const field_value_name = field_value_names ?
37  field_value_names[field_value] :
38  NULL;
39 
40  if (!field_value_name)
41  return print_number(buf, offset, field_value);
42  return get_len_or_sprintf(buf, offset, "%s", field_value_name);
43 }
44 
45 static unsigned int riscv_debug_reg_field_to_s(char *buf, unsigned int offset,
46  struct riscv_debug_reg_field_info field, struct riscv_debug_reg_ctx context,
47  uint64_t field_value)
48 {
49  const unsigned int name_len = get_len_or_sprintf(buf, offset, "%s=", field.name);
50 
51  return name_len + riscv_debug_reg_field_value_to_s(buf, offset + name_len,
52  field.values, field_value);
53 }
54 
55 static uint64_t riscv_debug_reg_field_value(struct riscv_debug_reg_field_info field, uint64_t value)
56 {
57  assert(field.msb < 64);
58  assert(field.msb >= field.lsb);
59  const uint64_t trailing_ones_mask = (uint64_t)(-1) >> (63 - field.msb);
60  return (value & trailing_ones_mask) >> field.lsb;
61 }
62 
63 static unsigned int riscv_debug_reg_fields_to_s(char *buf, unsigned int offset,
64  struct riscv_debug_reg_field_list (*get_next)(struct riscv_debug_reg_ctx contex),
65  struct riscv_debug_reg_ctx context, uint64_t value,
66  enum riscv_debug_reg_show show)
67 {
68  unsigned int curr = offset;
69  curr += get_len_or_sprintf(buf, curr, " {");
70  char *separator = "";
71  for (struct riscv_debug_reg_field_list list; get_next; get_next = list.get_next) {
72  list = get_next(context);
73 
74  uint64_t field_value = riscv_debug_reg_field_value(list.field, value);
75 
76  if (show == RISCV_DEBUG_REG_SHOW_ALL ||
78  (field_value != 0 ||
79  (list.field.values && list.field.values[0]))) ||
80  (show == RISCV_DEBUG_REG_HIDE_ALL_0 && field_value != 0)) {
81  curr += get_len_or_sprintf(buf, curr, separator);
82  curr += riscv_debug_reg_field_to_s(buf, curr, list.field, context,
83  field_value);
84  separator = " ";
85  }
86  }
87  curr += get_len_or_sprintf(buf, curr, "}");
88  return curr - offset;
89 }
90 
91 unsigned int riscv_debug_reg_to_s(char *buf, enum riscv_debug_reg_ordinal reg_ordinal,
92  struct riscv_debug_reg_ctx context, uint64_t value,
93  enum riscv_debug_reg_show show)
94 {
95  unsigned int length = 0;
96 
98 
99  length += get_len_or_sprintf(buf, length, "%s=", reg.name);
100  length += print_number(buf, length, value);
101 
102  if (reg.get_fields_head)
104  reg.get_fields_head, context, value, show);
105 
106  if (buf)
107  buf[length] = '\0';
108  return length;
109 }
struct riscv_debug_reg_info get_riscv_debug_reg_info(enum riscv_debug_reg_ordinal reg_ordinal)
riscv_debug_reg_ordinal
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)
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)
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 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)
This function is used to fill a buffer with a decoded string representation of register's value.
static unsigned int print_number(char *buf, unsigned int offset, uint64_t value)
static uint64_t riscv_debug_reg_field_value(struct riscv_debug_reg_field_info field, uint64_t value)
static unsigned int get_len_or_sprintf(char *buf, unsigned int curr, const char *format,...)
riscv_debug_reg_show
@ RISCV_DEBUG_REG_HIDE_ALL_0
@ RISCV_DEBUG_REG_SHOW_ALL
@ RISCV_DEBUG_REG_HIDE_UNNAMED_0
uint8_t length
Definition: esp_usb_jtag.c:1
static uint64_t field_value(uint64_t mask, uint64_t val)
Definition: field_helpers.h:37
Definition: register.h:111
const char * name
Definition: register.h:113
struct riscv_debug_reg_field_list(* get_next)(struct riscv_debug_reg_ctx context)
#define NULL
Definition: usb.h:16
uint8_t offset[4]
Definition: vdebug.c:9