xref: /openbmc/qemu/target/arm/gdbstub.c (revision 89f4f20e276e6e5dc08fca5e75e2bfbd92280072)
1fcf5ef2aSThomas Huth /*
2fcf5ef2aSThomas Huth  * ARM gdb server stub
3fcf5ef2aSThomas Huth  *
4fcf5ef2aSThomas Huth  * Copyright (c) 2003-2005 Fabrice Bellard
5fcf5ef2aSThomas Huth  * Copyright (c) 2013 SUSE LINUX Products GmbH
6fcf5ef2aSThomas Huth  *
7fcf5ef2aSThomas Huth  * This library is free software; you can redistribute it and/or
8fcf5ef2aSThomas Huth  * modify it under the terms of the GNU Lesser General Public
9fcf5ef2aSThomas Huth  * License as published by the Free Software Foundation; either
1050f57e09SChetan Pant  * version 2.1 of the License, or (at your option) any later version.
11fcf5ef2aSThomas Huth  *
12fcf5ef2aSThomas Huth  * This library is distributed in the hope that it will be useful,
13fcf5ef2aSThomas Huth  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14fcf5ef2aSThomas Huth  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15fcf5ef2aSThomas Huth  * Lesser General Public License for more details.
16fcf5ef2aSThomas Huth  *
17fcf5ef2aSThomas Huth  * You should have received a copy of the GNU Lesser General Public
18fcf5ef2aSThomas Huth  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19fcf5ef2aSThomas Huth  */
20fcf5ef2aSThomas Huth #include "qemu/osdep.h"
21fcf5ef2aSThomas Huth #include "cpu.h"
22*89f4f20eSPeter Maydell #include "internals.h"
23fcf5ef2aSThomas Huth #include "exec/gdbstub.h"
24fcf5ef2aSThomas Huth 
25200bf5b7SAbdallah Bouassida typedef struct RegisterSysregXmlParam {
26200bf5b7SAbdallah Bouassida     CPUState *cs;
27200bf5b7SAbdallah Bouassida     GString *s;
2832d6e32aSAlex Bennée     int n;
29200bf5b7SAbdallah Bouassida } RegisterSysregXmlParam;
30200bf5b7SAbdallah Bouassida 
31fcf5ef2aSThomas Huth /* Old gdb always expect FPA registers.  Newer (xml-aware) gdb only expect
32fcf5ef2aSThomas Huth    whatever the target description contains.  Due to a historical mishap
33fcf5ef2aSThomas Huth    the FPA registers appear in between core integer regs and the CPSR.
34fcf5ef2aSThomas Huth    We hack round this by giving the FPA regs zero size when talking to a
35fcf5ef2aSThomas Huth    newer gdb.  */
36fcf5ef2aSThomas Huth 
37a010bdbeSAlex Bennée int arm_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
38fcf5ef2aSThomas Huth {
39fcf5ef2aSThomas Huth     ARMCPU *cpu = ARM_CPU(cs);
40fcf5ef2aSThomas Huth     CPUARMState *env = &cpu->env;
41fcf5ef2aSThomas Huth 
42fcf5ef2aSThomas Huth     if (n < 16) {
43fcf5ef2aSThomas Huth         /* Core integer register.  */
44fcf5ef2aSThomas Huth         return gdb_get_reg32(mem_buf, env->regs[n]);
45fcf5ef2aSThomas Huth     }
46fcf5ef2aSThomas Huth     if (n < 24) {
47fcf5ef2aSThomas Huth         /* FPA registers.  */
48fcf5ef2aSThomas Huth         if (gdb_has_xml) {
49fcf5ef2aSThomas Huth             return 0;
50fcf5ef2aSThomas Huth         }
517b8c1527SPhilippe Mathieu-Daudé         return gdb_get_zeroes(mem_buf, 12);
52fcf5ef2aSThomas Huth     }
53fcf5ef2aSThomas Huth     switch (n) {
54fcf5ef2aSThomas Huth     case 24:
55fcf5ef2aSThomas Huth         /* FPA status register.  */
56fcf5ef2aSThomas Huth         if (gdb_has_xml) {
57fcf5ef2aSThomas Huth             return 0;
58fcf5ef2aSThomas Huth         }
59fcf5ef2aSThomas Huth         return gdb_get_reg32(mem_buf, 0);
60fcf5ef2aSThomas Huth     case 25:
61c888f7e0SPeter Maydell         /* CPSR, or XPSR for M-profile */
62c888f7e0SPeter Maydell         if (arm_feature(env, ARM_FEATURE_M)) {
63c888f7e0SPeter Maydell             return gdb_get_reg32(mem_buf, xpsr_read(env));
64c888f7e0SPeter Maydell         } else {
65fcf5ef2aSThomas Huth             return gdb_get_reg32(mem_buf, cpsr_read(env));
66fcf5ef2aSThomas Huth         }
67c888f7e0SPeter Maydell     }
68fcf5ef2aSThomas Huth     /* Unknown register.  */
69fcf5ef2aSThomas Huth     return 0;
70fcf5ef2aSThomas Huth }
71fcf5ef2aSThomas Huth 
72fcf5ef2aSThomas Huth int arm_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
73fcf5ef2aSThomas Huth {
74fcf5ef2aSThomas Huth     ARMCPU *cpu = ARM_CPU(cs);
75fcf5ef2aSThomas Huth     CPUARMState *env = &cpu->env;
76fcf5ef2aSThomas Huth     uint32_t tmp;
77fcf5ef2aSThomas Huth 
78fcf5ef2aSThomas Huth     tmp = ldl_p(mem_buf);
79fcf5ef2aSThomas Huth 
80fcf5ef2aSThomas Huth     /* Mask out low bit of PC to workaround gdb bugs.  This will probably
81fcf5ef2aSThomas Huth        cause problems if we ever implement the Jazelle DBX extensions.  */
82fcf5ef2aSThomas Huth     if (n == 15) {
83fcf5ef2aSThomas Huth         tmp &= ~1;
84fcf5ef2aSThomas Huth     }
85fcf5ef2aSThomas Huth 
86fcf5ef2aSThomas Huth     if (n < 16) {
87fcf5ef2aSThomas Huth         /* Core integer register.  */
88888f470fSPeter Maydell         if (n == 13 && arm_feature(env, ARM_FEATURE_M)) {
89888f470fSPeter Maydell             /* M profile SP low bits are always 0 */
90888f470fSPeter Maydell             tmp &= ~3;
91888f470fSPeter Maydell         }
92fcf5ef2aSThomas Huth         env->regs[n] = tmp;
93fcf5ef2aSThomas Huth         return 4;
94fcf5ef2aSThomas Huth     }
95fcf5ef2aSThomas Huth     if (n < 24) { /* 16-23 */
96fcf5ef2aSThomas Huth         /* FPA registers (ignored).  */
97fcf5ef2aSThomas Huth         if (gdb_has_xml) {
98fcf5ef2aSThomas Huth             return 0;
99fcf5ef2aSThomas Huth         }
100fcf5ef2aSThomas Huth         return 12;
101fcf5ef2aSThomas Huth     }
102fcf5ef2aSThomas Huth     switch (n) {
103fcf5ef2aSThomas Huth     case 24:
104fcf5ef2aSThomas Huth         /* FPA status register (ignored).  */
105fcf5ef2aSThomas Huth         if (gdb_has_xml) {
106fcf5ef2aSThomas Huth             return 0;
107fcf5ef2aSThomas Huth         }
108fcf5ef2aSThomas Huth         return 4;
109fcf5ef2aSThomas Huth     case 25:
110c888f7e0SPeter Maydell         /* CPSR, or XPSR for M-profile */
111c888f7e0SPeter Maydell         if (arm_feature(env, ARM_FEATURE_M)) {
112c888f7e0SPeter Maydell             /*
113c888f7e0SPeter Maydell              * Don't allow writing to XPSR.Exception as it can cause
114c888f7e0SPeter Maydell              * a transition into or out of handler mode (it's not
115c888f7e0SPeter Maydell              * writeable via the MSR insn so this is a reasonable
116c888f7e0SPeter Maydell              * restriction). Other fields are safe to update.
117c888f7e0SPeter Maydell              */
118c888f7e0SPeter Maydell             xpsr_write(env, tmp, ~XPSR_EXCP);
119c888f7e0SPeter Maydell         } else {
120fcf5ef2aSThomas Huth             cpsr_write(env, tmp, 0xffffffff, CPSRWriteByGDBStub);
121c888f7e0SPeter Maydell         }
122fcf5ef2aSThomas Huth         return 4;
123fcf5ef2aSThomas Huth     }
124fcf5ef2aSThomas Huth     /* Unknown register.  */
125fcf5ef2aSThomas Huth     return 0;
126fcf5ef2aSThomas Huth }
127200bf5b7SAbdallah Bouassida 
128*89f4f20eSPeter Maydell static int vfp_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg)
129*89f4f20eSPeter Maydell {
130*89f4f20eSPeter Maydell     ARMCPU *cpu = env_archcpu(env);
131*89f4f20eSPeter Maydell     int nregs = cpu_isar_feature(aa32_simd_r32, cpu) ? 32 : 16;
132*89f4f20eSPeter Maydell 
133*89f4f20eSPeter Maydell     /* VFP data registers are always little-endian.  */
134*89f4f20eSPeter Maydell     if (reg < nregs) {
135*89f4f20eSPeter Maydell         return gdb_get_reg64(buf, *aa32_vfp_dreg(env, reg));
136*89f4f20eSPeter Maydell     }
137*89f4f20eSPeter Maydell     if (arm_feature(env, ARM_FEATURE_NEON)) {
138*89f4f20eSPeter Maydell         /* Aliases for Q regs.  */
139*89f4f20eSPeter Maydell         nregs += 16;
140*89f4f20eSPeter Maydell         if (reg < nregs) {
141*89f4f20eSPeter Maydell             uint64_t *q = aa32_vfp_qreg(env, reg - 32);
142*89f4f20eSPeter Maydell             return gdb_get_reg128(buf, q[0], q[1]);
143*89f4f20eSPeter Maydell         }
144*89f4f20eSPeter Maydell     }
145*89f4f20eSPeter Maydell     switch (reg - nregs) {
146*89f4f20eSPeter Maydell     case 0:
147*89f4f20eSPeter Maydell         return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPSID]);
148*89f4f20eSPeter Maydell     case 1:
149*89f4f20eSPeter Maydell         return gdb_get_reg32(buf, vfp_get_fpscr(env));
150*89f4f20eSPeter Maydell     case 2:
151*89f4f20eSPeter Maydell         return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPEXC]);
152*89f4f20eSPeter Maydell     }
153*89f4f20eSPeter Maydell     return 0;
154*89f4f20eSPeter Maydell }
155*89f4f20eSPeter Maydell 
156*89f4f20eSPeter Maydell static int vfp_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
157*89f4f20eSPeter Maydell {
158*89f4f20eSPeter Maydell     ARMCPU *cpu = env_archcpu(env);
159*89f4f20eSPeter Maydell     int nregs = cpu_isar_feature(aa32_simd_r32, cpu) ? 32 : 16;
160*89f4f20eSPeter Maydell 
161*89f4f20eSPeter Maydell     if (reg < nregs) {
162*89f4f20eSPeter Maydell         *aa32_vfp_dreg(env, reg) = ldq_le_p(buf);
163*89f4f20eSPeter Maydell         return 8;
164*89f4f20eSPeter Maydell     }
165*89f4f20eSPeter Maydell     if (arm_feature(env, ARM_FEATURE_NEON)) {
166*89f4f20eSPeter Maydell         nregs += 16;
167*89f4f20eSPeter Maydell         if (reg < nregs) {
168*89f4f20eSPeter Maydell             uint64_t *q = aa32_vfp_qreg(env, reg - 32);
169*89f4f20eSPeter Maydell             q[0] = ldq_le_p(buf);
170*89f4f20eSPeter Maydell             q[1] = ldq_le_p(buf + 8);
171*89f4f20eSPeter Maydell             return 16;
172*89f4f20eSPeter Maydell         }
173*89f4f20eSPeter Maydell     }
174*89f4f20eSPeter Maydell     switch (reg - nregs) {
175*89f4f20eSPeter Maydell     case 0:
176*89f4f20eSPeter Maydell         env->vfp.xregs[ARM_VFP_FPSID] = ldl_p(buf);
177*89f4f20eSPeter Maydell         return 4;
178*89f4f20eSPeter Maydell     case 1:
179*89f4f20eSPeter Maydell         vfp_set_fpscr(env, ldl_p(buf));
180*89f4f20eSPeter Maydell         return 4;
181*89f4f20eSPeter Maydell     case 2:
182*89f4f20eSPeter Maydell         env->vfp.xregs[ARM_VFP_FPEXC] = ldl_p(buf) & (1 << 30);
183*89f4f20eSPeter Maydell         return 4;
184*89f4f20eSPeter Maydell     }
185*89f4f20eSPeter Maydell     return 0;
186*89f4f20eSPeter Maydell }
187*89f4f20eSPeter Maydell 
188*89f4f20eSPeter Maydell /**
189*89f4f20eSPeter Maydell  * arm_get/set_gdb_*: get/set a gdb register
190*89f4f20eSPeter Maydell  * @env: the CPU state
191*89f4f20eSPeter Maydell  * @buf: a buffer to copy to/from
192*89f4f20eSPeter Maydell  * @reg: register number (offset from start of group)
193*89f4f20eSPeter Maydell  *
194*89f4f20eSPeter Maydell  * We return the number of bytes copied
195*89f4f20eSPeter Maydell  */
196*89f4f20eSPeter Maydell 
197*89f4f20eSPeter Maydell static int arm_gdb_get_sysreg(CPUARMState *env, GByteArray *buf, int reg)
198*89f4f20eSPeter Maydell {
199*89f4f20eSPeter Maydell     ARMCPU *cpu = env_archcpu(env);
200*89f4f20eSPeter Maydell     const ARMCPRegInfo *ri;
201*89f4f20eSPeter Maydell     uint32_t key;
202*89f4f20eSPeter Maydell 
203*89f4f20eSPeter Maydell     key = cpu->dyn_sysreg_xml.data.cpregs.keys[reg];
204*89f4f20eSPeter Maydell     ri = get_arm_cp_reginfo(cpu->cp_regs, key);
205*89f4f20eSPeter Maydell     if (ri) {
206*89f4f20eSPeter Maydell         if (cpreg_field_is_64bit(ri)) {
207*89f4f20eSPeter Maydell             return gdb_get_reg64(buf, (uint64_t)read_raw_cp_reg(env, ri));
208*89f4f20eSPeter Maydell         } else {
209*89f4f20eSPeter Maydell             return gdb_get_reg32(buf, (uint32_t)read_raw_cp_reg(env, ri));
210*89f4f20eSPeter Maydell         }
211*89f4f20eSPeter Maydell     }
212*89f4f20eSPeter Maydell     return 0;
213*89f4f20eSPeter Maydell }
214*89f4f20eSPeter Maydell 
215*89f4f20eSPeter Maydell static int arm_gdb_set_sysreg(CPUARMState *env, uint8_t *buf, int reg)
216*89f4f20eSPeter Maydell {
217*89f4f20eSPeter Maydell     return 0;
218*89f4f20eSPeter Maydell }
219*89f4f20eSPeter Maydell 
220448d4d14SAlex Bennée static void arm_gen_one_xml_sysreg_tag(GString *s, DynamicGDBXMLInfo *dyn_xml,
221200bf5b7SAbdallah Bouassida                                        ARMCPRegInfo *ri, uint32_t ri_key,
22232d6e32aSAlex Bennée                                        int bitsize, int regnum)
223200bf5b7SAbdallah Bouassida {
224200bf5b7SAbdallah Bouassida     g_string_append_printf(s, "<reg name=\"%s\"", ri->name);
225200bf5b7SAbdallah Bouassida     g_string_append_printf(s, " bitsize=\"%d\"", bitsize);
22632d6e32aSAlex Bennée     g_string_append_printf(s, " regnum=\"%d\"", regnum);
227200bf5b7SAbdallah Bouassida     g_string_append_printf(s, " group=\"cp_regs\"/>");
228448d4d14SAlex Bennée     dyn_xml->data.cpregs.keys[dyn_xml->num] = ri_key;
229448d4d14SAlex Bennée     dyn_xml->num++;
230200bf5b7SAbdallah Bouassida }
231200bf5b7SAbdallah Bouassida 
232200bf5b7SAbdallah Bouassida static void arm_register_sysreg_for_xml(gpointer key, gpointer value,
233200bf5b7SAbdallah Bouassida                                         gpointer p)
234200bf5b7SAbdallah Bouassida {
235200bf5b7SAbdallah Bouassida     uint32_t ri_key = *(uint32_t *)key;
236200bf5b7SAbdallah Bouassida     ARMCPRegInfo *ri = value;
237200bf5b7SAbdallah Bouassida     RegisterSysregXmlParam *param = (RegisterSysregXmlParam *)p;
238200bf5b7SAbdallah Bouassida     GString *s = param->s;
239200bf5b7SAbdallah Bouassida     ARMCPU *cpu = ARM_CPU(param->cs);
240200bf5b7SAbdallah Bouassida     CPUARMState *env = &cpu->env;
241448d4d14SAlex Bennée     DynamicGDBXMLInfo *dyn_xml = &cpu->dyn_sysreg_xml;
242200bf5b7SAbdallah Bouassida 
243200bf5b7SAbdallah Bouassida     if (!(ri->type & (ARM_CP_NO_RAW | ARM_CP_NO_GDB))) {
244200bf5b7SAbdallah Bouassida         if (arm_feature(env, ARM_FEATURE_AARCH64)) {
245200bf5b7SAbdallah Bouassida             if (ri->state == ARM_CP_STATE_AA64) {
24632d6e32aSAlex Bennée                 arm_gen_one_xml_sysreg_tag(s , dyn_xml, ri, ri_key, 64,
24732d6e32aSAlex Bennée                                            param->n++);
248200bf5b7SAbdallah Bouassida             }
249200bf5b7SAbdallah Bouassida         } else {
250200bf5b7SAbdallah Bouassida             if (ri->state == ARM_CP_STATE_AA32) {
251200bf5b7SAbdallah Bouassida                 if (!arm_feature(env, ARM_FEATURE_EL3) &&
252200bf5b7SAbdallah Bouassida                     (ri->secure & ARM_CP_SECSTATE_S)) {
253200bf5b7SAbdallah Bouassida                     return;
254200bf5b7SAbdallah Bouassida                 }
255200bf5b7SAbdallah Bouassida                 if (ri->type & ARM_CP_64BIT) {
25632d6e32aSAlex Bennée                     arm_gen_one_xml_sysreg_tag(s , dyn_xml, ri, ri_key, 64,
25732d6e32aSAlex Bennée                                                param->n++);
258200bf5b7SAbdallah Bouassida                 } else {
25932d6e32aSAlex Bennée                     arm_gen_one_xml_sysreg_tag(s , dyn_xml, ri, ri_key, 32,
26032d6e32aSAlex Bennée                                                param->n++);
261200bf5b7SAbdallah Bouassida                 }
262200bf5b7SAbdallah Bouassida             }
263200bf5b7SAbdallah Bouassida         }
264200bf5b7SAbdallah Bouassida     }
265200bf5b7SAbdallah Bouassida }
266200bf5b7SAbdallah Bouassida 
26732d6e32aSAlex Bennée int arm_gen_dynamic_sysreg_xml(CPUState *cs, int base_reg)
268200bf5b7SAbdallah Bouassida {
269200bf5b7SAbdallah Bouassida     ARMCPU *cpu = ARM_CPU(cs);
270200bf5b7SAbdallah Bouassida     GString *s = g_string_new(NULL);
27132d6e32aSAlex Bennée     RegisterSysregXmlParam param = {cs, s, base_reg};
272200bf5b7SAbdallah Bouassida 
273448d4d14SAlex Bennée     cpu->dyn_sysreg_xml.num = 0;
274448d4d14SAlex Bennée     cpu->dyn_sysreg_xml.data.cpregs.keys = g_new(uint32_t, g_hash_table_size(cpu->cp_regs));
275200bf5b7SAbdallah Bouassida     g_string_printf(s, "<?xml version=\"1.0\"?>");
276200bf5b7SAbdallah Bouassida     g_string_append_printf(s, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">");
277200bf5b7SAbdallah Bouassida     g_string_append_printf(s, "<feature name=\"org.qemu.gdb.arm.sys.regs\">");
278200bf5b7SAbdallah Bouassida     g_hash_table_foreach(cpu->cp_regs, arm_register_sysreg_for_xml, &param);
279200bf5b7SAbdallah Bouassida     g_string_append_printf(s, "</feature>");
280448d4d14SAlex Bennée     cpu->dyn_sysreg_xml.desc = g_string_free(s, false);
281448d4d14SAlex Bennée     return cpu->dyn_sysreg_xml.num;
282200bf5b7SAbdallah Bouassida }
283200bf5b7SAbdallah Bouassida 
284d12379c5SAlex Bennée struct TypeSize {
285d12379c5SAlex Bennée     const char *gdb_type;
286d12379c5SAlex Bennée     int  size;
287d12379c5SAlex Bennée     const char sz, suffix;
288d12379c5SAlex Bennée };
289d12379c5SAlex Bennée 
290d12379c5SAlex Bennée static const struct TypeSize vec_lanes[] = {
291d12379c5SAlex Bennée     /* quads */
292d12379c5SAlex Bennée     { "uint128", 128, 'q', 'u' },
293d12379c5SAlex Bennée     { "int128", 128, 'q', 's' },
294d12379c5SAlex Bennée     /* 64 bit */
295797920b9SAlex Bennée     { "ieee_double", 64, 'd', 'f' },
296d12379c5SAlex Bennée     { "uint64", 64, 'd', 'u' },
297d12379c5SAlex Bennée     { "int64", 64, 'd', 's' },
298d12379c5SAlex Bennée     /* 32 bit */
299797920b9SAlex Bennée     { "ieee_single", 32, 's', 'f' },
300d12379c5SAlex Bennée     { "uint32", 32, 's', 'u' },
301d12379c5SAlex Bennée     { "int32", 32, 's', 's' },
302d12379c5SAlex Bennée     /* 16 bit */
303797920b9SAlex Bennée     { "ieee_half", 16, 'h', 'f' },
304d12379c5SAlex Bennée     { "uint16", 16, 'h', 'u' },
305d12379c5SAlex Bennée     { "int16", 16, 'h', 's' },
306d12379c5SAlex Bennée     /* bytes */
307d12379c5SAlex Bennée     { "uint8", 8, 'b', 'u' },
308d12379c5SAlex Bennée     { "int8", 8, 'b', 's' },
309d12379c5SAlex Bennée };
310d12379c5SAlex Bennée 
311d12379c5SAlex Bennée 
312d12379c5SAlex Bennée int arm_gen_dynamic_svereg_xml(CPUState *cs, int base_reg)
313d12379c5SAlex Bennée {
314d12379c5SAlex Bennée     ARMCPU *cpu = ARM_CPU(cs);
315d12379c5SAlex Bennée     GString *s = g_string_new(NULL);
316d12379c5SAlex Bennée     DynamicGDBXMLInfo *info = &cpu->dyn_svereg_xml;
317d12379c5SAlex Bennée     g_autoptr(GString) ts = g_string_new("");
318797920b9SAlex Bennée     int i, j, bits, reg_width = (cpu->sve_max_vq * 128);
319d12379c5SAlex Bennée     info->num = 0;
320d12379c5SAlex Bennée     g_string_printf(s, "<?xml version=\"1.0\"?>");
321d12379c5SAlex Bennée     g_string_append_printf(s, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">");
322797920b9SAlex Bennée     g_string_append_printf(s, "<feature name=\"org.gnu.gdb.aarch64.sve\">");
323d12379c5SAlex Bennée 
324d12379c5SAlex Bennée     /* First define types and totals in a whole VL */
325d12379c5SAlex Bennée     for (i = 0; i < ARRAY_SIZE(vec_lanes); i++) {
326d12379c5SAlex Bennée         int count = reg_width / vec_lanes[i].size;
327797920b9SAlex Bennée         g_string_printf(ts, "svev%c%c", vec_lanes[i].sz, vec_lanes[i].suffix);
328d12379c5SAlex Bennée         g_string_append_printf(s,
329d12379c5SAlex Bennée                                "<vector id=\"%s\" type=\"%s\" count=\"%d\"/>",
330d12379c5SAlex Bennée                                ts->str, vec_lanes[i].gdb_type, count);
331d12379c5SAlex Bennée     }
332d12379c5SAlex Bennée     /*
333d12379c5SAlex Bennée      * Now define a union for each size group containing unsigned and
334d12379c5SAlex Bennée      * signed and potentially float versions of each size from 128 to
335d12379c5SAlex Bennée      * 8 bits.
336d12379c5SAlex Bennée      */
337797920b9SAlex Bennée     for (bits = 128, i = 0; bits >= 8; bits /= 2, i++) {
338797920b9SAlex Bennée         const char suf[] = { 'q', 'd', 's', 'h', 'b' };
339797920b9SAlex Bennée         g_string_append_printf(s, "<union id=\"svevn%c\">", suf[i]);
340797920b9SAlex Bennée         for (j = 0; j < ARRAY_SIZE(vec_lanes); j++) {
341797920b9SAlex Bennée             if (vec_lanes[j].size == bits) {
342797920b9SAlex Bennée                 g_string_append_printf(s, "<field name=\"%c\" type=\"svev%c%c\"/>",
343797920b9SAlex Bennée                                        vec_lanes[j].suffix,
344797920b9SAlex Bennée                                        vec_lanes[j].sz, vec_lanes[j].suffix);
345d12379c5SAlex Bennée             }
346d12379c5SAlex Bennée         }
347d12379c5SAlex Bennée         g_string_append(s, "</union>");
348d12379c5SAlex Bennée     }
349d12379c5SAlex Bennée     /* And now the final union of unions */
350797920b9SAlex Bennée     g_string_append(s, "<union id=\"svev\">");
351797920b9SAlex Bennée     for (bits = 128, i = 0; bits >= 8; bits /= 2, i++) {
352797920b9SAlex Bennée         const char suf[] = { 'q', 'd', 's', 'h', 'b' };
353797920b9SAlex Bennée         g_string_append_printf(s, "<field name=\"%c\" type=\"svevn%c\"/>",
354797920b9SAlex Bennée                                suf[i], suf[i]);
355d12379c5SAlex Bennée     }
356d12379c5SAlex Bennée     g_string_append(s, "</union>");
357d12379c5SAlex Bennée 
358797920b9SAlex Bennée     /* Finally the sve prefix type */
359797920b9SAlex Bennée     g_string_append_printf(s,
360797920b9SAlex Bennée                            "<vector id=\"svep\" type=\"uint8\" count=\"%d\"/>",
361797920b9SAlex Bennée                            reg_width / 8);
362797920b9SAlex Bennée 
363d12379c5SAlex Bennée     /* Then define each register in parts for each vq */
364d12379c5SAlex Bennée     for (i = 0; i < 32; i++) {
365d12379c5SAlex Bennée         g_string_append_printf(s,
366d12379c5SAlex Bennée                                "<reg name=\"z%d\" bitsize=\"%d\""
367797920b9SAlex Bennée                                " regnum=\"%d\" type=\"svev\"/>",
368d12379c5SAlex Bennée                                i, reg_width, base_reg++);
369d12379c5SAlex Bennée         info->num++;
370d12379c5SAlex Bennée     }
371d12379c5SAlex Bennée     /* fpscr & status registers */
372d12379c5SAlex Bennée     g_string_append_printf(s, "<reg name=\"fpsr\" bitsize=\"32\""
373d12379c5SAlex Bennée                            " regnum=\"%d\" group=\"float\""
374d12379c5SAlex Bennée                            " type=\"int\"/>", base_reg++);
375d12379c5SAlex Bennée     g_string_append_printf(s, "<reg name=\"fpcr\" bitsize=\"32\""
376d12379c5SAlex Bennée                            " regnum=\"%d\" group=\"float\""
377d12379c5SAlex Bennée                            " type=\"int\"/>", base_reg++);
378d12379c5SAlex Bennée     info->num += 2;
379797920b9SAlex Bennée 
380d12379c5SAlex Bennée     for (i = 0; i < 16; i++) {
381d12379c5SAlex Bennée         g_string_append_printf(s,
382d12379c5SAlex Bennée                                "<reg name=\"p%d\" bitsize=\"%d\""
383797920b9SAlex Bennée                                " regnum=\"%d\" type=\"svep\"/>",
384d12379c5SAlex Bennée                                i, cpu->sve_max_vq * 16, base_reg++);
385d12379c5SAlex Bennée         info->num++;
386d12379c5SAlex Bennée     }
387d12379c5SAlex Bennée     g_string_append_printf(s,
388d12379c5SAlex Bennée                            "<reg name=\"ffr\" bitsize=\"%d\""
389d12379c5SAlex Bennée                            " regnum=\"%d\" group=\"vector\""
390797920b9SAlex Bennée                            " type=\"svep\"/>",
391d12379c5SAlex Bennée                            cpu->sve_max_vq * 16, base_reg++);
392d12379c5SAlex Bennée     g_string_append_printf(s,
393d12379c5SAlex Bennée                            "<reg name=\"vg\" bitsize=\"64\""
394797920b9SAlex Bennée                            " regnum=\"%d\" type=\"int\"/>",
395d12379c5SAlex Bennée                            base_reg++);
396d12379c5SAlex Bennée     info->num += 2;
397d12379c5SAlex Bennée     g_string_append_printf(s, "</feature>");
398d12379c5SAlex Bennée     cpu->dyn_svereg_xml.desc = g_string_free(s, false);
399d12379c5SAlex Bennée 
400d12379c5SAlex Bennée     return cpu->dyn_svereg_xml.num;
401d12379c5SAlex Bennée }
402d12379c5SAlex Bennée 
403d12379c5SAlex Bennée 
404200bf5b7SAbdallah Bouassida const char *arm_gdb_get_dynamic_xml(CPUState *cs, const char *xmlname)
405200bf5b7SAbdallah Bouassida {
406200bf5b7SAbdallah Bouassida     ARMCPU *cpu = ARM_CPU(cs);
407200bf5b7SAbdallah Bouassida 
408200bf5b7SAbdallah Bouassida     if (strcmp(xmlname, "system-registers.xml") == 0) {
409448d4d14SAlex Bennée         return cpu->dyn_sysreg_xml.desc;
410d12379c5SAlex Bennée     } else if (strcmp(xmlname, "sve-registers.xml") == 0) {
411d12379c5SAlex Bennée         return cpu->dyn_svereg_xml.desc;
412200bf5b7SAbdallah Bouassida     }
413200bf5b7SAbdallah Bouassida     return NULL;
414200bf5b7SAbdallah Bouassida }
415*89f4f20eSPeter Maydell 
416*89f4f20eSPeter Maydell void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
417*89f4f20eSPeter Maydell {
418*89f4f20eSPeter Maydell     CPUState *cs = CPU(cpu);
419*89f4f20eSPeter Maydell     CPUARMState *env = &cpu->env;
420*89f4f20eSPeter Maydell 
421*89f4f20eSPeter Maydell     if (arm_feature(env, ARM_FEATURE_AARCH64)) {
422*89f4f20eSPeter Maydell         /*
423*89f4f20eSPeter Maydell          * The lower part of each SVE register aliases to the FPU
424*89f4f20eSPeter Maydell          * registers so we don't need to include both.
425*89f4f20eSPeter Maydell          */
426*89f4f20eSPeter Maydell #ifdef TARGET_AARCH64
427*89f4f20eSPeter Maydell         if (isar_feature_aa64_sve(&cpu->isar)) {
428*89f4f20eSPeter Maydell             gdb_register_coprocessor(cs, arm_gdb_get_svereg, arm_gdb_set_svereg,
429*89f4f20eSPeter Maydell                                      arm_gen_dynamic_svereg_xml(cs, cs->gdb_num_regs),
430*89f4f20eSPeter Maydell                                      "sve-registers.xml", 0);
431*89f4f20eSPeter Maydell         } else {
432*89f4f20eSPeter Maydell             gdb_register_coprocessor(cs, aarch64_fpu_gdb_get_reg,
433*89f4f20eSPeter Maydell                                      aarch64_fpu_gdb_set_reg,
434*89f4f20eSPeter Maydell                                      34, "aarch64-fpu.xml", 0);
435*89f4f20eSPeter Maydell         }
436*89f4f20eSPeter Maydell #endif
437*89f4f20eSPeter Maydell     } else if (arm_feature(env, ARM_FEATURE_NEON)) {
438*89f4f20eSPeter Maydell         gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
439*89f4f20eSPeter Maydell                                  51, "arm-neon.xml", 0);
440*89f4f20eSPeter Maydell     } else if (cpu_isar_feature(aa32_simd_r32, cpu)) {
441*89f4f20eSPeter Maydell         gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
442*89f4f20eSPeter Maydell                                  35, "arm-vfp3.xml", 0);
443*89f4f20eSPeter Maydell     } else if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
444*89f4f20eSPeter Maydell         gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
445*89f4f20eSPeter Maydell                                  19, "arm-vfp.xml", 0);
446*89f4f20eSPeter Maydell     }
447*89f4f20eSPeter Maydell     gdb_register_coprocessor(cs, arm_gdb_get_sysreg, arm_gdb_set_sysreg,
448*89f4f20eSPeter Maydell                              arm_gen_dynamic_sysreg_xml(cs, cs->gdb_num_regs),
449*89f4f20eSPeter Maydell                              "system-registers.xml", 0);
450*89f4f20eSPeter Maydell 
451*89f4f20eSPeter Maydell }
452