]>
Commit | Line | Data |
---|---|---|
58850dad AF |
1 | /* |
2 | * ARM gdb server stub | |
3 | * | |
4 | * Copyright (c) 2003-2005 Fabrice Bellard | |
5 | * Copyright (c) 2013 SUSE LINUX Products GmbH | |
6 | * | |
7 | * This library is free software; you can redistribute it and/or | |
8 | * modify it under the terms of the GNU Lesser General Public | |
9 | * License as published by the Free Software Foundation; either | |
50f57e09 | 10 | * version 2.1 of the License, or (at your option) any later version. |
58850dad AF |
11 | * |
12 | * This library is distributed in the hope that it will be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | * Lesser General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU Lesser General Public | |
18 | * License along with this library; if not, see <http://www.gnu.org/licenses/>. | |
19 | */ | |
74c21bd0 | 20 | #include "qemu/osdep.h" |
33c11879 | 21 | #include "cpu.h" |
5b50e790 | 22 | #include "exec/gdbstub.h" |
cf7c6d10 RH |
23 | #include "internals.h" |
24 | #include "cpregs.h" | |
58850dad | 25 | |
200bf5b7 AB |
26 | typedef struct RegisterSysregXmlParam { |
27 | CPUState *cs; | |
28 | GString *s; | |
32d6e32a | 29 | int n; |
200bf5b7 AB |
30 | } RegisterSysregXmlParam; |
31 | ||
58850dad AF |
32 | /* Old gdb always expect FPA registers. Newer (xml-aware) gdb only expect |
33 | whatever the target description contains. Due to a historical mishap | |
34 | the FPA registers appear in between core integer regs and the CPSR. | |
35 | We hack round this by giving the FPA regs zero size when talking to a | |
36 | newer gdb. */ | |
37 | ||
a010bdbe | 38 | int arm_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) |
58850dad | 39 | { |
5b50e790 AF |
40 | ARMCPU *cpu = ARM_CPU(cs); |
41 | CPUARMState *env = &cpu->env; | |
42 | ||
58850dad AF |
43 | if (n < 16) { |
44 | /* Core integer register. */ | |
986a2998 | 45 | return gdb_get_reg32(mem_buf, env->regs[n]); |
58850dad AF |
46 | } |
47 | if (n < 24) { | |
48 | /* FPA registers. */ | |
49 | if (gdb_has_xml) { | |
50 | return 0; | |
51 | } | |
7b8c1527 | 52 | return gdb_get_zeroes(mem_buf, 12); |
58850dad AF |
53 | } |
54 | switch (n) { | |
55 | case 24: | |
56 | /* FPA status register. */ | |
57 | if (gdb_has_xml) { | |
58 | return 0; | |
59 | } | |
986a2998 | 60 | return gdb_get_reg32(mem_buf, 0); |
58850dad | 61 | case 25: |
c888f7e0 PM |
62 | /* CPSR, or XPSR for M-profile */ |
63 | if (arm_feature(env, ARM_FEATURE_M)) { | |
64 | return gdb_get_reg32(mem_buf, xpsr_read(env)); | |
65 | } else { | |
66 | return gdb_get_reg32(mem_buf, cpsr_read(env)); | |
67 | } | |
58850dad AF |
68 | } |
69 | /* Unknown register. */ | |
70 | return 0; | |
71 | } | |
72 | ||
5b50e790 | 73 | int arm_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) |
58850dad | 74 | { |
5b50e790 AF |
75 | ARMCPU *cpu = ARM_CPU(cs); |
76 | CPUARMState *env = &cpu->env; | |
58850dad AF |
77 | uint32_t tmp; |
78 | ||
79 | tmp = ldl_p(mem_buf); | |
80 | ||
7055fe4b RH |
81 | /* |
82 | * Mask out low bits of PC to workaround gdb bugs. | |
83 | * This avoids an assert in thumb_tr_translate_insn, because it is | |
84 | * architecturally impossible to misalign the pc. | |
85 | * This will probably cause problems if we ever implement the | |
86 | * Jazelle DBX extensions. | |
87 | */ | |
58850dad AF |
88 | if (n == 15) { |
89 | tmp &= ~1; | |
90 | } | |
91 | ||
92 | if (n < 16) { | |
93 | /* Core integer register. */ | |
888f470f PM |
94 | if (n == 13 && arm_feature(env, ARM_FEATURE_M)) { |
95 | /* M profile SP low bits are always 0 */ | |
96 | tmp &= ~3; | |
97 | } | |
58850dad AF |
98 | env->regs[n] = tmp; |
99 | return 4; | |
100 | } | |
101 | if (n < 24) { /* 16-23 */ | |
102 | /* FPA registers (ignored). */ | |
103 | if (gdb_has_xml) { | |
104 | return 0; | |
105 | } | |
106 | return 12; | |
107 | } | |
108 | switch (n) { | |
109 | case 24: | |
110 | /* FPA status register (ignored). */ | |
111 | if (gdb_has_xml) { | |
112 | return 0; | |
113 | } | |
114 | return 4; | |
115 | case 25: | |
c888f7e0 PM |
116 | /* CPSR, or XPSR for M-profile */ |
117 | if (arm_feature(env, ARM_FEATURE_M)) { | |
118 | /* | |
119 | * Don't allow writing to XPSR.Exception as it can cause | |
120 | * a transition into or out of handler mode (it's not | |
121 | * writeable via the MSR insn so this is a reasonable | |
122 | * restriction). Other fields are safe to update. | |
123 | */ | |
124 | xpsr_write(env, tmp, ~XPSR_EXCP); | |
125 | } else { | |
126 | cpsr_write(env, tmp, 0xffffffff, CPSRWriteByGDBStub); | |
127 | } | |
58850dad AF |
128 | return 4; |
129 | } | |
130 | /* Unknown register. */ | |
131 | return 0; | |
132 | } | |
200bf5b7 | 133 | |
89f4f20e PM |
134 | static int vfp_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg) |
135 | { | |
136 | ARMCPU *cpu = env_archcpu(env); | |
137 | int nregs = cpu_isar_feature(aa32_simd_r32, cpu) ? 32 : 16; | |
138 | ||
139 | /* VFP data registers are always little-endian. */ | |
140 | if (reg < nregs) { | |
141 | return gdb_get_reg64(buf, *aa32_vfp_dreg(env, reg)); | |
142 | } | |
143 | if (arm_feature(env, ARM_FEATURE_NEON)) { | |
144 | /* Aliases for Q regs. */ | |
145 | nregs += 16; | |
146 | if (reg < nregs) { | |
147 | uint64_t *q = aa32_vfp_qreg(env, reg - 32); | |
148 | return gdb_get_reg128(buf, q[0], q[1]); | |
149 | } | |
150 | } | |
151 | switch (reg - nregs) { | |
152 | case 0: | |
89f4f20e | 153 | return gdb_get_reg32(buf, vfp_get_fpscr(env)); |
89f4f20e PM |
154 | } |
155 | return 0; | |
156 | } | |
157 | ||
158 | static int vfp_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg) | |
159 | { | |
160 | ARMCPU *cpu = env_archcpu(env); | |
161 | int nregs = cpu_isar_feature(aa32_simd_r32, cpu) ? 32 : 16; | |
162 | ||
163 | if (reg < nregs) { | |
164 | *aa32_vfp_dreg(env, reg) = ldq_le_p(buf); | |
165 | return 8; | |
166 | } | |
167 | if (arm_feature(env, ARM_FEATURE_NEON)) { | |
168 | nregs += 16; | |
169 | if (reg < nregs) { | |
170 | uint64_t *q = aa32_vfp_qreg(env, reg - 32); | |
171 | q[0] = ldq_le_p(buf); | |
172 | q[1] = ldq_le_p(buf + 8); | |
173 | return 16; | |
174 | } | |
175 | } | |
176 | switch (reg - nregs) { | |
177 | case 0: | |
b355f08a | 178 | vfp_set_fpscr(env, ldl_p(buf)); |
89f4f20e | 179 | return 4; |
b355f08a PM |
180 | } |
181 | return 0; | |
182 | } | |
183 | ||
184 | static int vfp_gdb_get_sysreg(CPUARMState *env, GByteArray *buf, int reg) | |
185 | { | |
186 | switch (reg) { | |
187 | case 0: | |
188 | return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPSID]); | |
89f4f20e | 189 | case 1: |
b355f08a PM |
190 | return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPEXC]); |
191 | } | |
192 | return 0; | |
193 | } | |
194 | ||
195 | static int vfp_gdb_set_sysreg(CPUARMState *env, uint8_t *buf, int reg) | |
196 | { | |
197 | switch (reg) { | |
198 | case 0: | |
199 | env->vfp.xregs[ARM_VFP_FPSID] = ldl_p(buf); | |
89f4f20e | 200 | return 4; |
b355f08a | 201 | case 1: |
89f4f20e PM |
202 | env->vfp.xregs[ARM_VFP_FPEXC] = ldl_p(buf) & (1 << 30); |
203 | return 4; | |
204 | } | |
205 | return 0; | |
206 | } | |
207 | ||
dbd9e084 PM |
208 | static int mve_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg) |
209 | { | |
210 | switch (reg) { | |
211 | case 0: | |
212 | return gdb_get_reg32(buf, env->v7m.vpr); | |
213 | default: | |
214 | return 0; | |
215 | } | |
216 | } | |
217 | ||
218 | static int mve_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg) | |
219 | { | |
220 | switch (reg) { | |
221 | case 0: | |
222 | env->v7m.vpr = ldl_p(buf); | |
223 | return 4; | |
224 | default: | |
225 | return 0; | |
226 | } | |
227 | } | |
228 | ||
89f4f20e PM |
229 | /** |
230 | * arm_get/set_gdb_*: get/set a gdb register | |
231 | * @env: the CPU state | |
232 | * @buf: a buffer to copy to/from | |
233 | * @reg: register number (offset from start of group) | |
234 | * | |
235 | * We return the number of bytes copied | |
236 | */ | |
237 | ||
238 | static int arm_gdb_get_sysreg(CPUARMState *env, GByteArray *buf, int reg) | |
239 | { | |
240 | ARMCPU *cpu = env_archcpu(env); | |
241 | const ARMCPRegInfo *ri; | |
242 | uint32_t key; | |
243 | ||
244 | key = cpu->dyn_sysreg_xml.data.cpregs.keys[reg]; | |
245 | ri = get_arm_cp_reginfo(cpu->cp_regs, key); | |
246 | if (ri) { | |
247 | if (cpreg_field_is_64bit(ri)) { | |
248 | return gdb_get_reg64(buf, (uint64_t)read_raw_cp_reg(env, ri)); | |
249 | } else { | |
250 | return gdb_get_reg32(buf, (uint32_t)read_raw_cp_reg(env, ri)); | |
251 | } | |
252 | } | |
253 | return 0; | |
254 | } | |
255 | ||
256 | static int arm_gdb_set_sysreg(CPUARMState *env, uint8_t *buf, int reg) | |
257 | { | |
258 | return 0; | |
259 | } | |
260 | ||
448d4d14 AB |
261 | static void arm_gen_one_xml_sysreg_tag(GString *s, DynamicGDBXMLInfo *dyn_xml, |
262 | ARMCPRegInfo *ri, uint32_t ri_key, | |
32d6e32a | 263 | int bitsize, int regnum) |
200bf5b7 AB |
264 | { |
265 | g_string_append_printf(s, "<reg name=\"%s\"", ri->name); | |
266 | g_string_append_printf(s, " bitsize=\"%d\"", bitsize); | |
32d6e32a | 267 | g_string_append_printf(s, " regnum=\"%d\"", regnum); |
200bf5b7 | 268 | g_string_append_printf(s, " group=\"cp_regs\"/>"); |
448d4d14 AB |
269 | dyn_xml->data.cpregs.keys[dyn_xml->num] = ri_key; |
270 | dyn_xml->num++; | |
200bf5b7 AB |
271 | } |
272 | ||
273 | static void arm_register_sysreg_for_xml(gpointer key, gpointer value, | |
274 | gpointer p) | |
275 | { | |
276 | uint32_t ri_key = *(uint32_t *)key; | |
277 | ARMCPRegInfo *ri = value; | |
278 | RegisterSysregXmlParam *param = (RegisterSysregXmlParam *)p; | |
279 | GString *s = param->s; | |
280 | ARMCPU *cpu = ARM_CPU(param->cs); | |
281 | CPUARMState *env = &cpu->env; | |
448d4d14 | 282 | DynamicGDBXMLInfo *dyn_xml = &cpu->dyn_sysreg_xml; |
200bf5b7 AB |
283 | |
284 | if (!(ri->type & (ARM_CP_NO_RAW | ARM_CP_NO_GDB))) { | |
285 | if (arm_feature(env, ARM_FEATURE_AARCH64)) { | |
286 | if (ri->state == ARM_CP_STATE_AA64) { | |
32d6e32a AB |
287 | arm_gen_one_xml_sysreg_tag(s , dyn_xml, ri, ri_key, 64, |
288 | param->n++); | |
200bf5b7 AB |
289 | } |
290 | } else { | |
291 | if (ri->state == ARM_CP_STATE_AA32) { | |
292 | if (!arm_feature(env, ARM_FEATURE_EL3) && | |
293 | (ri->secure & ARM_CP_SECSTATE_S)) { | |
294 | return; | |
295 | } | |
296 | if (ri->type & ARM_CP_64BIT) { | |
32d6e32a AB |
297 | arm_gen_one_xml_sysreg_tag(s , dyn_xml, ri, ri_key, 64, |
298 | param->n++); | |
200bf5b7 | 299 | } else { |
32d6e32a AB |
300 | arm_gen_one_xml_sysreg_tag(s , dyn_xml, ri, ri_key, 32, |
301 | param->n++); | |
200bf5b7 AB |
302 | } |
303 | } | |
304 | } | |
305 | } | |
306 | } | |
307 | ||
32d6e32a | 308 | int arm_gen_dynamic_sysreg_xml(CPUState *cs, int base_reg) |
200bf5b7 AB |
309 | { |
310 | ARMCPU *cpu = ARM_CPU(cs); | |
311 | GString *s = g_string_new(NULL); | |
32d6e32a | 312 | RegisterSysregXmlParam param = {cs, s, base_reg}; |
200bf5b7 | 313 | |
448d4d14 AB |
314 | cpu->dyn_sysreg_xml.num = 0; |
315 | cpu->dyn_sysreg_xml.data.cpregs.keys = g_new(uint32_t, g_hash_table_size(cpu->cp_regs)); | |
200bf5b7 AB |
316 | g_string_printf(s, "<?xml version=\"1.0\"?>"); |
317 | g_string_append_printf(s, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">"); | |
318 | g_string_append_printf(s, "<feature name=\"org.qemu.gdb.arm.sys.regs\">"); | |
319 | g_hash_table_foreach(cpu->cp_regs, arm_register_sysreg_for_xml, ¶m); | |
320 | g_string_append_printf(s, "</feature>"); | |
448d4d14 AB |
321 | cpu->dyn_sysreg_xml.desc = g_string_free(s, false); |
322 | return cpu->dyn_sysreg_xml.num; | |
200bf5b7 AB |
323 | } |
324 | ||
d12379c5 AB |
325 | struct TypeSize { |
326 | const char *gdb_type; | |
327 | int size; | |
328 | const char sz, suffix; | |
329 | }; | |
330 | ||
331 | static const struct TypeSize vec_lanes[] = { | |
332 | /* quads */ | |
333 | { "uint128", 128, 'q', 'u' }, | |
334 | { "int128", 128, 'q', 's' }, | |
335 | /* 64 bit */ | |
797920b9 | 336 | { "ieee_double", 64, 'd', 'f' }, |
d12379c5 AB |
337 | { "uint64", 64, 'd', 'u' }, |
338 | { "int64", 64, 'd', 's' }, | |
d12379c5 | 339 | /* 32 bit */ |
797920b9 | 340 | { "ieee_single", 32, 's', 'f' }, |
d12379c5 AB |
341 | { "uint32", 32, 's', 'u' }, |
342 | { "int32", 32, 's', 's' }, | |
d12379c5 | 343 | /* 16 bit */ |
797920b9 | 344 | { "ieee_half", 16, 'h', 'f' }, |
d12379c5 AB |
345 | { "uint16", 16, 'h', 'u' }, |
346 | { "int16", 16, 'h', 's' }, | |
d12379c5 AB |
347 | /* bytes */ |
348 | { "uint8", 8, 'b', 'u' }, | |
349 | { "int8", 8, 'b', 's' }, | |
350 | }; | |
351 | ||
352 | ||
353 | int arm_gen_dynamic_svereg_xml(CPUState *cs, int base_reg) | |
354 | { | |
355 | ARMCPU *cpu = ARM_CPU(cs); | |
356 | GString *s = g_string_new(NULL); | |
357 | DynamicGDBXMLInfo *info = &cpu->dyn_svereg_xml; | |
358 | g_autoptr(GString) ts = g_string_new(""); | |
797920b9 | 359 | int i, j, bits, reg_width = (cpu->sve_max_vq * 128); |
d12379c5 AB |
360 | info->num = 0; |
361 | g_string_printf(s, "<?xml version=\"1.0\"?>"); | |
362 | g_string_append_printf(s, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">"); | |
797920b9 | 363 | g_string_append_printf(s, "<feature name=\"org.gnu.gdb.aarch64.sve\">"); |
d12379c5 AB |
364 | |
365 | /* First define types and totals in a whole VL */ | |
366 | for (i = 0; i < ARRAY_SIZE(vec_lanes); i++) { | |
367 | int count = reg_width / vec_lanes[i].size; | |
797920b9 | 368 | g_string_printf(ts, "svev%c%c", vec_lanes[i].sz, vec_lanes[i].suffix); |
d12379c5 AB |
369 | g_string_append_printf(s, |
370 | "<vector id=\"%s\" type=\"%s\" count=\"%d\"/>", | |
371 | ts->str, vec_lanes[i].gdb_type, count); | |
372 | } | |
373 | /* | |
374 | * Now define a union for each size group containing unsigned and | |
375 | * signed and potentially float versions of each size from 128 to | |
376 | * 8 bits. | |
377 | */ | |
797920b9 AB |
378 | for (bits = 128, i = 0; bits >= 8; bits /= 2, i++) { |
379 | const char suf[] = { 'q', 'd', 's', 'h', 'b' }; | |
380 | g_string_append_printf(s, "<union id=\"svevn%c\">", suf[i]); | |
381 | for (j = 0; j < ARRAY_SIZE(vec_lanes); j++) { | |
382 | if (vec_lanes[j].size == bits) { | |
383 | g_string_append_printf(s, "<field name=\"%c\" type=\"svev%c%c\"/>", | |
384 | vec_lanes[j].suffix, | |
385 | vec_lanes[j].sz, vec_lanes[j].suffix); | |
d12379c5 AB |
386 | } |
387 | } | |
388 | g_string_append(s, "</union>"); | |
389 | } | |
390 | /* And now the final union of unions */ | |
797920b9 AB |
391 | g_string_append(s, "<union id=\"svev\">"); |
392 | for (bits = 128, i = 0; bits >= 8; bits /= 2, i++) { | |
393 | const char suf[] = { 'q', 'd', 's', 'h', 'b' }; | |
394 | g_string_append_printf(s, "<field name=\"%c\" type=\"svevn%c\"/>", | |
395 | suf[i], suf[i]); | |
d12379c5 AB |
396 | } |
397 | g_string_append(s, "</union>"); | |
398 | ||
797920b9 AB |
399 | /* Finally the sve prefix type */ |
400 | g_string_append_printf(s, | |
401 | "<vector id=\"svep\" type=\"uint8\" count=\"%d\"/>", | |
402 | reg_width / 8); | |
403 | ||
d12379c5 AB |
404 | /* Then define each register in parts for each vq */ |
405 | for (i = 0; i < 32; i++) { | |
406 | g_string_append_printf(s, | |
407 | "<reg name=\"z%d\" bitsize=\"%d\"" | |
797920b9 | 408 | " regnum=\"%d\" type=\"svev\"/>", |
d12379c5 AB |
409 | i, reg_width, base_reg++); |
410 | info->num++; | |
411 | } | |
412 | /* fpscr & status registers */ | |
413 | g_string_append_printf(s, "<reg name=\"fpsr\" bitsize=\"32\"" | |
414 | " regnum=\"%d\" group=\"float\"" | |
415 | " type=\"int\"/>", base_reg++); | |
416 | g_string_append_printf(s, "<reg name=\"fpcr\" bitsize=\"32\"" | |
417 | " regnum=\"%d\" group=\"float\"" | |
418 | " type=\"int\"/>", base_reg++); | |
419 | info->num += 2; | |
797920b9 | 420 | |
d12379c5 AB |
421 | for (i = 0; i < 16; i++) { |
422 | g_string_append_printf(s, | |
423 | "<reg name=\"p%d\" bitsize=\"%d\"" | |
797920b9 | 424 | " regnum=\"%d\" type=\"svep\"/>", |
d12379c5 AB |
425 | i, cpu->sve_max_vq * 16, base_reg++); |
426 | info->num++; | |
427 | } | |
428 | g_string_append_printf(s, | |
429 | "<reg name=\"ffr\" bitsize=\"%d\"" | |
430 | " regnum=\"%d\" group=\"vector\"" | |
797920b9 | 431 | " type=\"svep\"/>", |
d12379c5 AB |
432 | cpu->sve_max_vq * 16, base_reg++); |
433 | g_string_append_printf(s, | |
434 | "<reg name=\"vg\" bitsize=\"64\"" | |
797920b9 | 435 | " regnum=\"%d\" type=\"int\"/>", |
d12379c5 AB |
436 | base_reg++); |
437 | info->num += 2; | |
438 | g_string_append_printf(s, "</feature>"); | |
439 | cpu->dyn_svereg_xml.desc = g_string_free(s, false); | |
440 | ||
441 | return cpu->dyn_svereg_xml.num; | |
442 | } | |
443 | ||
444 | ||
200bf5b7 AB |
445 | const char *arm_gdb_get_dynamic_xml(CPUState *cs, const char *xmlname) |
446 | { | |
447 | ARMCPU *cpu = ARM_CPU(cs); | |
448 | ||
449 | if (strcmp(xmlname, "system-registers.xml") == 0) { | |
448d4d14 | 450 | return cpu->dyn_sysreg_xml.desc; |
d12379c5 AB |
451 | } else if (strcmp(xmlname, "sve-registers.xml") == 0) { |
452 | return cpu->dyn_svereg_xml.desc; | |
200bf5b7 AB |
453 | } |
454 | return NULL; | |
455 | } | |
89f4f20e PM |
456 | |
457 | void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu) | |
458 | { | |
459 | CPUState *cs = CPU(cpu); | |
460 | CPUARMState *env = &cpu->env; | |
461 | ||
462 | if (arm_feature(env, ARM_FEATURE_AARCH64)) { | |
463 | /* | |
464 | * The lower part of each SVE register aliases to the FPU | |
465 | * registers so we don't need to include both. | |
466 | */ | |
467 | #ifdef TARGET_AARCH64 | |
468 | if (isar_feature_aa64_sve(&cpu->isar)) { | |
469 | gdb_register_coprocessor(cs, arm_gdb_get_svereg, arm_gdb_set_svereg, | |
470 | arm_gen_dynamic_svereg_xml(cs, cs->gdb_num_regs), | |
471 | "sve-registers.xml", 0); | |
472 | } else { | |
473 | gdb_register_coprocessor(cs, aarch64_fpu_gdb_get_reg, | |
474 | aarch64_fpu_gdb_set_reg, | |
475 | 34, "aarch64-fpu.xml", 0); | |
476 | } | |
477 | #endif | |
b355f08a PM |
478 | } else { |
479 | if (arm_feature(env, ARM_FEATURE_NEON)) { | |
480 | gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg, | |
481 | 49, "arm-neon.xml", 0); | |
482 | } else if (cpu_isar_feature(aa32_simd_r32, cpu)) { | |
483 | gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg, | |
484 | 33, "arm-vfp3.xml", 0); | |
485 | } else if (cpu_isar_feature(aa32_vfp_simd, cpu)) { | |
486 | gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg, | |
487 | 17, "arm-vfp.xml", 0); | |
488 | } | |
489 | if (!arm_feature(env, ARM_FEATURE_M)) { | |
490 | /* | |
491 | * A and R profile have FP sysregs FPEXC and FPSID that we | |
492 | * expose to gdb. | |
493 | */ | |
494 | gdb_register_coprocessor(cs, vfp_gdb_get_sysreg, vfp_gdb_set_sysreg, | |
495 | 2, "arm-vfp-sysregs.xml", 0); | |
496 | } | |
89f4f20e | 497 | } |
dbd9e084 PM |
498 | if (cpu_isar_feature(aa32_mve, cpu)) { |
499 | gdb_register_coprocessor(cs, mve_gdb_get_reg, mve_gdb_set_reg, | |
500 | 1, "arm-m-profile-mve.xml", 0); | |
501 | } | |
89f4f20e PM |
502 | gdb_register_coprocessor(cs, arm_gdb_get_sysreg, arm_gdb_set_sysreg, |
503 | arm_gen_dynamic_sysreg_xml(cs, cs->gdb_num_regs), | |
504 | "system-registers.xml", 0); | |
505 | ||
506 | } |