OpenOCD
riscv_reg_impl.h
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #ifndef OPENOCD_TARGET_RISCV_RISCV_REG_IMPL_H
4 #define OPENOCD_TARGET_RISCV_RISCV_REG_IMPL_H
5 
6 #include "gdb_regs.h"
7 #include "riscv.h"
8 #include "target/target.h"
9 #include "target/register.h"
10 #include <assert.h>
11 
19 static inline bool riscv_reg_impl_is_initialized(const struct reg *reg)
20 {
21  assert(reg);
22  if (!reg->feature) {
23  const struct reg default_reg = {0};
24  assert(!memcmp(&default_reg, reg, sizeof(*reg)));
25  return false;
26  }
27  assert(reg->arch_info);
28  assert(((riscv_reg_info_t *)reg->arch_info)->target);
29  assert((!reg->exist && !reg->value) || (reg->exist && reg->value));
30  assert(reg->valid || !reg->dirty);
31  return true;
32 }
38 
40 int riscv_reg_impl_init_cache_entry(struct target *target, uint32_t regno,
41  bool exist, const struct reg_arch_type *reg_type);
42 
47 bool riscv_reg_impl_gdb_regno_exist(const struct target *target, uint32_t regno);
48 
50 int riscv_reg_impl_set_exist(const struct target *target,
51  uint32_t regno, bool exist);
52 
54 struct reg *riscv_reg_impl_cache_entry(const struct target *target,
55  uint32_t number);
56 
58 struct target *riscv_reg_impl_get_target(const struct reg *reg);
59 
60 static inline void init_shared_reg_info(struct target *target)
61 {
63  info->shared_reg_info.target = target;
64  info->shared_reg_info.custom_number = 0;
65 }
66 
69 static inline void riscv_reg_impl_init_vector_reg_type(const struct target *target)
70 {
72  static struct reg_data_type type_uint8 = { .type = REG_TYPE_UINT8, .id = "uint8" };
73  static struct reg_data_type type_uint16 = { .type = REG_TYPE_UINT16, .id = "uint16" };
74  static struct reg_data_type type_uint32 = { .type = REG_TYPE_UINT32, .id = "uint32" };
75  static struct reg_data_type type_uint64 = { .type = REG_TYPE_UINT64, .id = "uint64" };
76  static struct reg_data_type type_uint128 = { .type = REG_TYPE_UINT128, .id = "uint128" };
77 
78  /* This is roughly the XML we want:
79  * <vector id="bytes" type="uint8" count="16"/>
80  * <vector id="shorts" type="uint16" count="8"/>
81  * <vector id="words" type="uint32" count="4"/>
82  * <vector id="longs" type="uint64" count="2"/>
83  * <vector id="quads" type="uint128" count="1"/>
84  * <union id="riscv_vector_type">
85  * <field name="b" type="bytes"/>
86  * <field name="s" type="shorts"/>
87  * <field name="w" type="words"/>
88  * <field name="l" type="longs"/>
89  * <field name="q" type="quads"/>
90  * </union>
91  */
92 
93  info->vector_uint8.type = &type_uint8;
94  info->vector_uint8.count = riscv_vlenb(target);
95  info->type_uint8_vector.type = REG_TYPE_ARCH_DEFINED;
96  info->type_uint8_vector.id = "bytes";
97  info->type_uint8_vector.type_class = REG_TYPE_CLASS_VECTOR;
98  info->type_uint8_vector.reg_type_vector = &info->vector_uint8;
99 
100  info->vector_uint16.type = &type_uint16;
101  info->vector_uint16.count = riscv_vlenb(target) / 2;
102  info->type_uint16_vector.type = REG_TYPE_ARCH_DEFINED;
103  info->type_uint16_vector.id = "shorts";
104  info->type_uint16_vector.type_class = REG_TYPE_CLASS_VECTOR;
105  info->type_uint16_vector.reg_type_vector = &info->vector_uint16;
106 
107  info->vector_uint32.type = &type_uint32;
108  info->vector_uint32.count = riscv_vlenb(target) / 4;
109  info->type_uint32_vector.type = REG_TYPE_ARCH_DEFINED;
110  info->type_uint32_vector.id = "words";
111  info->type_uint32_vector.type_class = REG_TYPE_CLASS_VECTOR;
112  info->type_uint32_vector.reg_type_vector = &info->vector_uint32;
113 
114  info->vector_uint64.type = &type_uint64;
115  info->vector_uint64.count = riscv_vlenb(target) / 8;
116  info->type_uint64_vector.type = REG_TYPE_ARCH_DEFINED;
117  info->type_uint64_vector.id = "longs";
118  info->type_uint64_vector.type_class = REG_TYPE_CLASS_VECTOR;
119  info->type_uint64_vector.reg_type_vector = &info->vector_uint64;
120 
121  info->vector_uint128.type = &type_uint128;
122  info->vector_uint128.count = riscv_vlenb(target) / 16;
123  info->type_uint128_vector.type = REG_TYPE_ARCH_DEFINED;
124  info->type_uint128_vector.id = "quads";
125  info->type_uint128_vector.type_class = REG_TYPE_CLASS_VECTOR;
126  info->type_uint128_vector.reg_type_vector = &info->vector_uint128;
127 
128  info->vector_fields[0].name = "b";
129  info->vector_fields[0].type = &info->type_uint8_vector;
130  if (riscv_vlenb(target) >= 2) {
131  info->vector_fields[0].next = info->vector_fields + 1;
132  info->vector_fields[1].name = "s";
133  info->vector_fields[1].type = &info->type_uint16_vector;
134  } else {
135  info->vector_fields[0].next = NULL;
136  }
137  if (riscv_vlenb(target) >= 4) {
138  info->vector_fields[1].next = info->vector_fields + 2;
139  info->vector_fields[2].name = "w";
140  info->vector_fields[2].type = &info->type_uint32_vector;
141  } else {
142  info->vector_fields[1].next = NULL;
143  }
144  if (riscv_vlenb(target) >= 8) {
145  info->vector_fields[2].next = info->vector_fields + 3;
146  info->vector_fields[3].name = "l";
147  info->vector_fields[3].type = &info->type_uint64_vector;
148  } else {
149  info->vector_fields[2].next = NULL;
150  }
151  if (riscv_vlenb(target) >= 16) {
152  info->vector_fields[3].next = info->vector_fields + 4;
153  info->vector_fields[4].name = "q";
154  info->vector_fields[4].type = &info->type_uint128_vector;
155  } else {
156  info->vector_fields[3].next = NULL;
157  }
158  info->vector_fields[4].next = NULL;
159 
160  info->vector_union.fields = info->vector_fields;
161 
162  info->type_vector.type = REG_TYPE_ARCH_DEFINED;
163  info->type_vector.id = "riscv_vector";
164  info->type_vector.type_class = REG_TYPE_CLASS_UNION;
165  info->type_vector.reg_type_union = &info->vector_union;
166 }
167 
169 int riscv_reg_impl_expose_csrs(const struct target *target);
170 
172 void riscv_reg_impl_hide_csrs(const struct target *target);
173 
182 static inline bool riscv_reg_impl_gdb_regno_cacheable(enum gdb_regno regno,
183  bool is_write)
184 {
185  if (regno == GDB_REGNO_ZERO)
186  return !is_write;
187 
188  /* GPRs, FPRs, vector registers are just normal data stores. */
189  if (regno <= GDB_REGNO_XPR31 ||
190  (regno >= GDB_REGNO_FPR0 && regno <= GDB_REGNO_FPR31) ||
191  (regno >= GDB_REGNO_V0 && regno <= GDB_REGNO_V31))
192  return true;
193 
194  /* Most CSRs won't change value on us, but we can't assume it about arbitrary
195  * CSRs. */
196  switch (regno) {
197  case GDB_REGNO_DPC:
198  case GDB_REGNO_VSTART:
199  case GDB_REGNO_VXSAT:
200  case GDB_REGNO_VXRM:
201  case GDB_REGNO_VLENB:
202  case GDB_REGNO_VL:
203  case GDB_REGNO_VTYPE:
204  case GDB_REGNO_MISA:
205  case GDB_REGNO_DCSR:
206  case GDB_REGNO_DSCRATCH0:
207  case GDB_REGNO_MEPC:
208  case GDB_REGNO_SATP:
209  /*
210  * WARL registers might not contain the value we just wrote, but
211  * these ones won't spontaneously change their value either. *
212  */
213  return !is_write;
214 
215  case GDB_REGNO_TSELECT: /* I think this should be above, but then it doesn't work. */
216  case GDB_REGNO_TDATA1: /* Changes value when tselect is changed. */
217  case GDB_REGNO_TDATA2: /* Changes value when tselect is changed. */
218  default:
219  return false;
220  }
221 }
222 #endif /* OPENOCD_TARGET_RISCV_RISCV_REG_IMPL_H */
enum esirisc_reg_num number
Definition: esirisc.c:87
gdb_regno
Definition: gdb_regs.h:10
@ GDB_REGNO_DPC
Definition: gdb_regs.h:99
@ GDB_REGNO_SATP
Definition: gdb_regs.h:105
@ GDB_REGNO_VXRM
Definition: gdb_regs.h:88
@ GDB_REGNO_ZERO
Definition: gdb_regs.h:11
@ GDB_REGNO_VTYPE
Definition: gdb_regs.h:92
@ GDB_REGNO_VXSAT
Definition: gdb_regs.h:87
@ GDB_REGNO_TSELECT
Definition: gdb_regs.h:93
@ GDB_REGNO_FPR31
Definition: gdb_regs.h:81
@ GDB_REGNO_FPR0
Definition: gdb_regs.h:48
@ GDB_REGNO_V0
Definition: gdb_regs.h:117
@ GDB_REGNO_DSCRATCH0
Definition: gdb_regs.h:101
@ GDB_REGNO_VL
Definition: gdb_regs.h:91
@ GDB_REGNO_TDATA1
Definition: gdb_regs.h:94
@ GDB_REGNO_VSTART
Definition: gdb_regs.h:86
@ GDB_REGNO_XPR31
Definition: gdb_regs.h:45
@ GDB_REGNO_MEPC
Definition: gdb_regs.h:103
@ GDB_REGNO_VLENB
Definition: gdb_regs.h:90
@ GDB_REGNO_V31
Definition: gdb_regs.h:124
@ GDB_REGNO_TDATA2
Definition: gdb_regs.h:95
@ GDB_REGNO_MISA
Definition: gdb_regs.h:98
@ GDB_REGNO_DCSR
Definition: gdb_regs.h:100
reg_type
Definition: register.h:19
@ REG_TYPE_UINT16
Definition: register.h:29
@ REG_TYPE_UINT32
Definition: register.h:30
@ REG_TYPE_UINT128
Definition: register.h:32
@ REG_TYPE_UINT64
Definition: register.h:31
@ REG_TYPE_ARCH_DEFINED
Definition: register.h:38
@ REG_TYPE_UINT8
Definition: register.h:28
@ REG_TYPE_CLASS_VECTOR
Definition: register.h:93
@ REG_TYPE_CLASS_UNION
Definition: register.h:94
unsigned int riscv_vlenb(const struct target *target)
Definition: riscv.c:6066
#define RISCV_INFO(R)
Definition: riscv.h:426
static bool riscv_reg_impl_is_initialized(const struct reg *reg)
This file describes the helpers to use during register cache initialization of a RISC-V target.
int riscv_reg_impl_set_exist(const struct target *target, uint32_t regno, bool exist)
Mark register as existing or not.
Definition: riscv_reg.c:601
void riscv_reg_impl_hide_csrs(const struct target *target)
Hide additional CSRs, as specified by riscv_info_t::hide_csr list.
Definition: riscv_reg.c:736
static void init_shared_reg_info(struct target *target)
bool riscv_reg_impl_gdb_regno_exist(const struct target *target, uint32_t regno)
For most registers, returns whether they exist or not.
Definition: riscv_reg.c:368
struct target * riscv_reg_impl_get_target(const struct reg *reg)
Return the target that owns the cache entry.
Definition: riscv_reg.c:207
int riscv_reg_impl_expose_csrs(const struct target *target)
Expose additional CSRs, as specified by riscv_info_t::expose_csr list.
Definition: riscv_reg.c:709
int riscv_reg_impl_init_cache_entry(struct target *target, uint32_t regno, bool exist, const struct reg_arch_type *reg_type)
Initialize register.
Definition: riscv_reg.c:608
int riscv_reg_impl_init_cache(struct target *target)
Initialize register cache.
Definition: riscv_reg.c:678
static void riscv_reg_impl_init_vector_reg_type(const struct target *target)
TODO: vector register type description can be moved into riscv013_info_t, since 0....
struct reg * riscv_reg_impl_cache_entry(const struct target *target, uint32_t number)
Return the entry in the register cache of the target.
Definition: riscv_reg.c:571
static bool riscv_reg_impl_gdb_regno_cacheable(enum gdb_regno regno, bool is_write)
If write is true: return true iff we are guaranteed that the register will contain exactly the value ...
struct target * target
Definition: rtt/rtt.c:26
enum reg_type type
Definition: register.h:100
Definition: register.h:111
bool valid
Definition: register.h:126
bool exist
Definition: register.h:128
uint8_t * value
Definition: register.h:122
struct reg_feature * feature
Definition: register.h:117
void * arch_info
Definition: register.h:140
bool dirty
Definition: register.h:124
Definition: target.h:119
static struct ublast_lowlevel_priv info
#define NULL
Definition: usb.h:16