1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19#include "qemu/osdep.h"
20#include "exec/gdbstub.h"
21#include "cpu.h"
22
23struct TypeSize {
24 const char *gdb_type;
25 const char *id;
26 int size;
27 const char suffix;
28};
29
30static const struct TypeSize vec_lanes[] = {
31
32 { "uint128", "quads", 128, 'q' },
33
34 { "uint64", "longs", 64, 'l' },
35
36 { "uint32", "words", 32, 'w' },
37
38 { "uint16", "shorts", 16, 's' },
39
40
41
42
43
44
45
46 { "uint8", "bytes", 8, 'b' },
47};
48
49int riscv_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
50{
51 RISCVCPU *cpu = RISCV_CPU(cs);
52 CPURISCVState *env = &cpu->env;
53 target_ulong tmp;
54
55 if (n < 32) {
56 tmp = env->gpr[n];
57 } else if (n == 32) {
58 tmp = env->pc;
59 } else {
60 return 0;
61 }
62
63 switch (env->misa_mxl_max) {
64 case MXL_RV32:
65 return gdb_get_reg32(mem_buf, tmp);
66 case MXL_RV64:
67 case MXL_RV128:
68 return gdb_get_reg64(mem_buf, tmp);
69 default:
70 g_assert_not_reached();
71 }
72 return 0;
73}
74
75int riscv_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
76{
77 RISCVCPU *cpu = RISCV_CPU(cs);
78 CPURISCVState *env = &cpu->env;
79 int length = 0;
80 target_ulong tmp;
81
82 switch (env->misa_mxl_max) {
83 case MXL_RV32:
84 tmp = (int32_t)ldl_p(mem_buf);
85 length = 4;
86 break;
87 case MXL_RV64:
88 case MXL_RV128:
89 if (env->xl < MXL_RV64) {
90 tmp = (int32_t)ldq_p(mem_buf);
91 } else {
92 tmp = ldq_p(mem_buf);
93 }
94 length = 8;
95 break;
96 default:
97 g_assert_not_reached();
98 }
99 if (n > 0 && n < 32) {
100 env->gpr[n] = tmp;
101 } else if (n == 32) {
102 env->pc = tmp;
103 }
104
105 return length;
106}
107
108static int riscv_gdb_get_fpu(CPURISCVState *env, GByteArray *buf, int n)
109{
110 if (n < 32) {
111 if (env->misa_ext & RVD) {
112 return gdb_get_reg64(buf, env->fpr[n]);
113 }
114 if (env->misa_ext & RVF) {
115 return gdb_get_reg32(buf, env->fpr[n]);
116 }
117
118 } else if (n < 36 && n > 32) {
119 target_ulong val = 0;
120 int result;
121
122
123
124
125
126 result = riscv_csrrw_debug(env, n - 32, &val,
127 0, 0);
128 if (result == RISCV_EXCP_NONE) {
129 return gdb_get_regl(buf, val);
130 }
131 }
132 return 0;
133}
134
135static int riscv_gdb_set_fpu(CPURISCVState *env, uint8_t *mem_buf, int n)
136{
137 if (n < 32) {
138 env->fpr[n] = ldq_p(mem_buf);
139 return sizeof(uint64_t);
140
141 } else if (n < 36 && n > 32) {
142 target_ulong val = ldtul_p(mem_buf);
143 int result;
144
145
146
147
148
149 result = riscv_csrrw_debug(env, n - 32, NULL,
150 val, -1);
151 if (result == RISCV_EXCP_NONE) {
152 return sizeof(target_ulong);
153 }
154 }
155 return 0;
156}
157
158
159
160
161
162
163
164
165static int riscv_gdb_vector_csrno(int num_regs)
166{
167
168
169
170
171 switch (num_regs) {
172 case 32:
173 return CSR_VSTART;
174 case 33:
175 return CSR_VXSAT;
176 case 34:
177 return CSR_VXRM;
178 case 35:
179 return CSR_VCSR;
180 case 36:
181 return CSR_VL;
182 case 37:
183 return CSR_VTYPE;
184 case 38:
185 return CSR_VLENB;
186 default:
187
188 return 0;
189 }
190}
191
192static int riscv_gdb_get_vector(CPURISCVState *env, GByteArray *buf, int n)
193{
194 uint16_t vlenb = env_archcpu(env)->cfg.vlen >> 3;
195 if (n < 32) {
196 int i;
197 int cnt = 0;
198 for (i = 0; i < vlenb; i += 8) {
199 cnt += gdb_get_reg64(buf,
200 env->vreg[(n * vlenb + i) / 8]);
201 }
202 return cnt;
203 }
204
205 int csrno = riscv_gdb_vector_csrno(n);
206
207 if (!csrno) {
208 return 0;
209 }
210
211 target_ulong val = 0;
212 int result = riscv_csrrw_debug(env, csrno, &val, 0, 0);
213
214 if (result == 0) {
215 return gdb_get_regl(buf, val);
216 }
217
218 return 0;
219}
220
221static int riscv_gdb_set_vector(CPURISCVState *env, uint8_t *mem_buf, int n)
222{
223 uint16_t vlenb = env_archcpu(env)->cfg.vlen >> 3;
224 if (n < 32) {
225 int i;
226 for (i = 0; i < vlenb; i += 8) {
227 env->vreg[(n * vlenb + i) / 8] = ldq_p(mem_buf + i);
228 }
229 return vlenb;
230 }
231
232 int csrno = riscv_gdb_vector_csrno(n);
233
234 if (!csrno) {
235 return 0;
236 }
237
238 target_ulong val = ldtul_p(mem_buf);
239 int result = riscv_csrrw_debug(env, csrno, NULL, val, -1);
240
241 if (result == 0) {
242 return sizeof(target_ulong);
243 }
244
245 return 0;
246}
247
248static int riscv_gdb_get_csr(CPURISCVState *env, GByteArray *buf, int n)
249{
250 if (n < CSR_TABLE_SIZE) {
251 target_ulong val = 0;
252 int result;
253
254 result = riscv_csrrw_debug(env, n, &val, 0, 0);
255 if (result == RISCV_EXCP_NONE) {
256 return gdb_get_regl(buf, val);
257 }
258 }
259 return 0;
260}
261
262static int riscv_gdb_set_csr(CPURISCVState *env, uint8_t *mem_buf, int n)
263{
264 if (n < CSR_TABLE_SIZE) {
265 target_ulong val = ldtul_p(mem_buf);
266 int result;
267
268 result = riscv_csrrw_debug(env, n, NULL, val, -1);
269 if (result == RISCV_EXCP_NONE) {
270 return sizeof(target_ulong);
271 }
272 }
273 return 0;
274}
275
276static int riscv_gdb_get_virtual(CPURISCVState *cs, GByteArray *buf, int n)
277{
278 if (n == 0) {
279#ifdef CONFIG_USER_ONLY
280 return gdb_get_regl(buf, 0);
281#else
282 return gdb_get_regl(buf, cs->priv);
283#endif
284 }
285 return 0;
286}
287
288static int riscv_gdb_set_virtual(CPURISCVState *cs, uint8_t *mem_buf, int n)
289{
290 if (n == 0) {
291#ifndef CONFIG_USER_ONLY
292 cs->priv = ldtul_p(mem_buf) & 0x3;
293 if (cs->priv == PRV_H) {
294 cs->priv = PRV_S;
295 }
296#endif
297 return sizeof(target_ulong);
298 }
299 return 0;
300}
301
302static int riscv_gen_dynamic_csr_xml(CPUState *cs, int base_reg)
303{
304 RISCVCPU *cpu = RISCV_CPU(cs);
305 CPURISCVState *env = &cpu->env;
306 GString *s = g_string_new(NULL);
307 riscv_csr_predicate_fn predicate;
308 int bitsize = 16 << env->misa_mxl_max;
309 int i;
310
311
312 if (bitsize > 64) {
313 bitsize = 64;
314 }
315
316 g_string_printf(s, "<?xml version=\"1.0\"?>");
317 g_string_append_printf(s, "<!DOCTYPE feature SYSTEM \"gdb-target.dtd\">");
318 g_string_append_printf(s, "<feature name=\"org.gnu.gdb.riscv.csr\">");
319
320 for (i = 0; i < CSR_TABLE_SIZE; i++) {
321 predicate = csr_ops[i].predicate;
322 if (predicate && (predicate(env, i) == RISCV_EXCP_NONE)) {
323 if (csr_ops[i].name) {
324 g_string_append_printf(s, "<reg name=\"%s\"", csr_ops[i].name);
325 } else {
326 g_string_append_printf(s, "<reg name=\"csr%03x\"", i);
327 }
328 g_string_append_printf(s, " bitsize=\"%d\"", bitsize);
329 g_string_append_printf(s, " regnum=\"%d\"/>", base_reg + i);
330 }
331 }
332
333 g_string_append_printf(s, "</feature>");
334
335 cpu->dyn_csr_xml = g_string_free(s, false);
336 return CSR_TABLE_SIZE;
337}
338
339static int ricsv_gen_dynamic_vector_xml(CPUState *cs, int base_reg)
340{
341 RISCVCPU *cpu = RISCV_CPU(cs);
342 GString *s = g_string_new(NULL);
343 g_autoptr(GString) ts = g_string_new("");
344 int reg_width = cpu->cfg.vlen;
345 int num_regs = 0;
346 int i;
347
348 g_string_printf(s, "<?xml version=\"1.0\"?>");
349 g_string_append_printf(s, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">");
350 g_string_append_printf(s, "<feature name=\"org.gnu.gdb.riscv.vector\">");
351
352
353 for (i = 0; i < ARRAY_SIZE(vec_lanes); i++) {
354 int count = reg_width / vec_lanes[i].size;
355 g_string_printf(ts, "%s", vec_lanes[i].id);
356 g_string_append_printf(s,
357 "<vector id=\"%s\" type=\"%s\" count=\"%d\"/>",
358 ts->str, vec_lanes[i].gdb_type, count);
359 }
360
361
362 g_string_append_printf(s, "<union id=\"riscv_vector\">");
363 for (i = 0; i < ARRAY_SIZE(vec_lanes); i++) {
364 g_string_append_printf(s, "<field name=\"%c\" type=\"%s\"/>",
365 vec_lanes[i].suffix,
366 vec_lanes[i].id);
367 }
368 g_string_append(s, "</union>");
369
370
371 for (i = 0; i < 32; i++) {
372 g_string_append_printf(s,
373 "<reg name=\"v%d\" bitsize=\"%d\""
374 " regnum=\"%d\" group=\"vector\""
375 " type=\"riscv_vector\"/>",
376 i, reg_width, base_reg++);
377 num_regs++;
378 }
379
380
381 const char *vector_csrs[7] = {
382 "vstart", "vxsat", "vxrm", "vcsr",
383 "vl", "vtype", "vlenb"
384 };
385
386 for (i = 0; i < 7; i++) {
387 g_string_append_printf(s,
388 "<reg name=\"%s\" bitsize=\"%d\""
389 " regnum=\"%d\" group=\"vector\""
390 " type=\"int\"/>",
391 vector_csrs[i], TARGET_LONG_BITS, base_reg++);
392 num_regs++;
393 }
394
395 g_string_append_printf(s, "</feature>");
396
397 cpu->dyn_vreg_xml = g_string_free(s, false);
398 return num_regs;
399}
400
401void riscv_cpu_register_gdb_regs_for_features(CPUState *cs)
402{
403 RISCVCPU *cpu = RISCV_CPU(cs);
404 CPURISCVState *env = &cpu->env;
405 if (env->misa_ext & RVD) {
406 gdb_register_coprocessor(cs, riscv_gdb_get_fpu, riscv_gdb_set_fpu,
407 36, "riscv-64bit-fpu.xml", 0);
408 } else if (env->misa_ext & RVF) {
409 gdb_register_coprocessor(cs, riscv_gdb_get_fpu, riscv_gdb_set_fpu,
410 36, "riscv-32bit-fpu.xml", 0);
411 }
412 if (env->misa_ext & RVV) {
413 gdb_register_coprocessor(cs, riscv_gdb_get_vector, riscv_gdb_set_vector,
414 ricsv_gen_dynamic_vector_xml(cs,
415 cs->gdb_num_regs),
416 "riscv-vector.xml", 0);
417 }
418 switch (env->misa_mxl_max) {
419 case MXL_RV32:
420 gdb_register_coprocessor(cs, riscv_gdb_get_virtual,
421 riscv_gdb_set_virtual,
422 1, "riscv-32bit-virtual.xml", 0);
423 break;
424 case MXL_RV64:
425 case MXL_RV128:
426 gdb_register_coprocessor(cs, riscv_gdb_get_virtual,
427 riscv_gdb_set_virtual,
428 1, "riscv-64bit-virtual.xml", 0);
429 break;
430 default:
431 g_assert_not_reached();
432 }
433
434 gdb_register_coprocessor(cs, riscv_gdb_get_csr, riscv_gdb_set_csr,
435 riscv_gen_dynamic_csr_xml(cs, cs->gdb_num_regs),
436 "riscv-csr.xml", 0);
437}
438