xref: /openbmc/qemu/target/arm/gdbstub.c (revision 963a6b91)
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"
22fcf5ef2aSThomas Huth #include "exec/gdbstub.h"
23cf7c6d10SRichard Henderson #include "internals.h"
24cf7c6d10SRichard Henderson #include "cpregs.h"
25fcf5ef2aSThomas Huth 
26200bf5b7SAbdallah Bouassida typedef struct RegisterSysregXmlParam {
27200bf5b7SAbdallah Bouassida     CPUState *cs;
28200bf5b7SAbdallah Bouassida     GString *s;
2932d6e32aSAlex Bennée     int n;
30200bf5b7SAbdallah Bouassida } RegisterSysregXmlParam;
31200bf5b7SAbdallah Bouassida 
32fcf5ef2aSThomas Huth /* Old gdb always expect FPA registers.  Newer (xml-aware) gdb only expect
33fcf5ef2aSThomas Huth    whatever the target description contains.  Due to a historical mishap
34fcf5ef2aSThomas Huth    the FPA registers appear in between core integer regs and the CPSR.
35fcf5ef2aSThomas Huth    We hack round this by giving the FPA regs zero size when talking to a
36fcf5ef2aSThomas Huth    newer gdb.  */
37fcf5ef2aSThomas Huth 
38a010bdbeSAlex Bennée int arm_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
39fcf5ef2aSThomas Huth {
40fcf5ef2aSThomas Huth     ARMCPU *cpu = ARM_CPU(cs);
41fcf5ef2aSThomas Huth     CPUARMState *env = &cpu->env;
42fcf5ef2aSThomas Huth 
43fcf5ef2aSThomas Huth     if (n < 16) {
44fcf5ef2aSThomas Huth         /* Core integer register.  */
45fcf5ef2aSThomas Huth         return gdb_get_reg32(mem_buf, env->regs[n]);
46fcf5ef2aSThomas Huth     }
47fcf5ef2aSThomas Huth     if (n < 24) {
48fcf5ef2aSThomas Huth         /* FPA registers.  */
49fcf5ef2aSThomas Huth         if (gdb_has_xml) {
50fcf5ef2aSThomas Huth             return 0;
51fcf5ef2aSThomas Huth         }
527b8c1527SPhilippe Mathieu-Daudé         return gdb_get_zeroes(mem_buf, 12);
53fcf5ef2aSThomas Huth     }
54fcf5ef2aSThomas Huth     switch (n) {
55fcf5ef2aSThomas Huth     case 24:
56fcf5ef2aSThomas Huth         /* FPA status register.  */
57fcf5ef2aSThomas Huth         if (gdb_has_xml) {
58fcf5ef2aSThomas Huth             return 0;
59fcf5ef2aSThomas Huth         }
60fcf5ef2aSThomas Huth         return gdb_get_reg32(mem_buf, 0);
61fcf5ef2aSThomas Huth     case 25:
62c888f7e0SPeter Maydell         /* CPSR, or XPSR for M-profile */
63c888f7e0SPeter Maydell         if (arm_feature(env, ARM_FEATURE_M)) {
64c888f7e0SPeter Maydell             return gdb_get_reg32(mem_buf, xpsr_read(env));
65c888f7e0SPeter Maydell         } else {
66fcf5ef2aSThomas Huth             return gdb_get_reg32(mem_buf, cpsr_read(env));
67fcf5ef2aSThomas Huth         }
68c888f7e0SPeter Maydell     }
69fcf5ef2aSThomas Huth     /* Unknown register.  */
70fcf5ef2aSThomas Huth     return 0;
71fcf5ef2aSThomas Huth }
72fcf5ef2aSThomas Huth 
73fcf5ef2aSThomas Huth int arm_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
74fcf5ef2aSThomas Huth {
75fcf5ef2aSThomas Huth     ARMCPU *cpu = ARM_CPU(cs);
76fcf5ef2aSThomas Huth     CPUARMState *env = &cpu->env;
77fcf5ef2aSThomas Huth     uint32_t tmp;
78fcf5ef2aSThomas Huth 
79fcf5ef2aSThomas Huth     tmp = ldl_p(mem_buf);
80fcf5ef2aSThomas Huth 
817055fe4bSRichard Henderson     /*
827055fe4bSRichard Henderson      * Mask out low bits of PC to workaround gdb bugs.
837055fe4bSRichard Henderson      * This avoids an assert in thumb_tr_translate_insn, because it is
847055fe4bSRichard Henderson      * architecturally impossible to misalign the pc.
857055fe4bSRichard Henderson      * This will probably cause problems if we ever implement the
867055fe4bSRichard Henderson      * Jazelle DBX extensions.
877055fe4bSRichard Henderson      */
88fcf5ef2aSThomas Huth     if (n == 15) {
89fcf5ef2aSThomas Huth         tmp &= ~1;
90fcf5ef2aSThomas Huth     }
91fcf5ef2aSThomas Huth 
92fcf5ef2aSThomas Huth     if (n < 16) {
93fcf5ef2aSThomas Huth         /* Core integer register.  */
94888f470fSPeter Maydell         if (n == 13 && arm_feature(env, ARM_FEATURE_M)) {
95888f470fSPeter Maydell             /* M profile SP low bits are always 0 */
96888f470fSPeter Maydell             tmp &= ~3;
97888f470fSPeter Maydell         }
98fcf5ef2aSThomas Huth         env->regs[n] = tmp;
99fcf5ef2aSThomas Huth         return 4;
100fcf5ef2aSThomas Huth     }
101fcf5ef2aSThomas Huth     if (n < 24) { /* 16-23 */
102fcf5ef2aSThomas Huth         /* FPA registers (ignored).  */
103fcf5ef2aSThomas Huth         if (gdb_has_xml) {
104fcf5ef2aSThomas Huth             return 0;
105fcf5ef2aSThomas Huth         }
106fcf5ef2aSThomas Huth         return 12;
107fcf5ef2aSThomas Huth     }
108fcf5ef2aSThomas Huth     switch (n) {
109fcf5ef2aSThomas Huth     case 24:
110fcf5ef2aSThomas Huth         /* FPA status register (ignored).  */
111fcf5ef2aSThomas Huth         if (gdb_has_xml) {
112fcf5ef2aSThomas Huth             return 0;
113fcf5ef2aSThomas Huth         }
114fcf5ef2aSThomas Huth         return 4;
115fcf5ef2aSThomas Huth     case 25:
116c888f7e0SPeter Maydell         /* CPSR, or XPSR for M-profile */
117c888f7e0SPeter Maydell         if (arm_feature(env, ARM_FEATURE_M)) {
118c888f7e0SPeter Maydell             /*
119c888f7e0SPeter Maydell              * Don't allow writing to XPSR.Exception as it can cause
120c888f7e0SPeter Maydell              * a transition into or out of handler mode (it's not
1219323e79fSPeter Maydell              * writable via the MSR insn so this is a reasonable
122c888f7e0SPeter Maydell              * restriction). Other fields are safe to update.
123c888f7e0SPeter Maydell              */
124c888f7e0SPeter Maydell             xpsr_write(env, tmp, ~XPSR_EXCP);
125c888f7e0SPeter Maydell         } else {
126fcf5ef2aSThomas Huth             cpsr_write(env, tmp, 0xffffffff, CPSRWriteByGDBStub);
127c888f7e0SPeter Maydell         }
128fcf5ef2aSThomas Huth         return 4;
129fcf5ef2aSThomas Huth     }
130fcf5ef2aSThomas Huth     /* Unknown register.  */
131fcf5ef2aSThomas Huth     return 0;
132fcf5ef2aSThomas Huth }
133200bf5b7SAbdallah Bouassida 
13489f4f20eSPeter Maydell static int vfp_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg)
13589f4f20eSPeter Maydell {
13689f4f20eSPeter Maydell     ARMCPU *cpu = env_archcpu(env);
13789f4f20eSPeter Maydell     int nregs = cpu_isar_feature(aa32_simd_r32, cpu) ? 32 : 16;
13889f4f20eSPeter Maydell 
13989f4f20eSPeter Maydell     /* VFP data registers are always little-endian.  */
14089f4f20eSPeter Maydell     if (reg < nregs) {
14189f4f20eSPeter Maydell         return gdb_get_reg64(buf, *aa32_vfp_dreg(env, reg));
14289f4f20eSPeter Maydell     }
14389f4f20eSPeter Maydell     if (arm_feature(env, ARM_FEATURE_NEON)) {
14489f4f20eSPeter Maydell         /* Aliases for Q regs.  */
14589f4f20eSPeter Maydell         nregs += 16;
14689f4f20eSPeter Maydell         if (reg < nregs) {
14789f4f20eSPeter Maydell             uint64_t *q = aa32_vfp_qreg(env, reg - 32);
14889f4f20eSPeter Maydell             return gdb_get_reg128(buf, q[0], q[1]);
14989f4f20eSPeter Maydell         }
15089f4f20eSPeter Maydell     }
15189f4f20eSPeter Maydell     switch (reg - nregs) {
15289f4f20eSPeter Maydell     case 0:
15389f4f20eSPeter Maydell         return gdb_get_reg32(buf, vfp_get_fpscr(env));
15489f4f20eSPeter Maydell     }
15589f4f20eSPeter Maydell     return 0;
15689f4f20eSPeter Maydell }
15789f4f20eSPeter Maydell 
15889f4f20eSPeter Maydell static int vfp_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
15989f4f20eSPeter Maydell {
16089f4f20eSPeter Maydell     ARMCPU *cpu = env_archcpu(env);
16189f4f20eSPeter Maydell     int nregs = cpu_isar_feature(aa32_simd_r32, cpu) ? 32 : 16;
16289f4f20eSPeter Maydell 
16389f4f20eSPeter Maydell     if (reg < nregs) {
16489f4f20eSPeter Maydell         *aa32_vfp_dreg(env, reg) = ldq_le_p(buf);
16589f4f20eSPeter Maydell         return 8;
16689f4f20eSPeter Maydell     }
16789f4f20eSPeter Maydell     if (arm_feature(env, ARM_FEATURE_NEON)) {
16889f4f20eSPeter Maydell         nregs += 16;
16989f4f20eSPeter Maydell         if (reg < nregs) {
17089f4f20eSPeter Maydell             uint64_t *q = aa32_vfp_qreg(env, reg - 32);
17189f4f20eSPeter Maydell             q[0] = ldq_le_p(buf);
17289f4f20eSPeter Maydell             q[1] = ldq_le_p(buf + 8);
17389f4f20eSPeter Maydell             return 16;
17489f4f20eSPeter Maydell         }
17589f4f20eSPeter Maydell     }
17689f4f20eSPeter Maydell     switch (reg - nregs) {
17789f4f20eSPeter Maydell     case 0:
178b355f08aSPeter Maydell         vfp_set_fpscr(env, ldl_p(buf));
179b355f08aSPeter Maydell         return 4;
180b355f08aSPeter Maydell     }
181b355f08aSPeter Maydell     return 0;
182b355f08aSPeter Maydell }
183b355f08aSPeter Maydell 
184b355f08aSPeter Maydell static int vfp_gdb_get_sysreg(CPUARMState *env, GByteArray *buf, int reg)
185b355f08aSPeter Maydell {
186b355f08aSPeter Maydell     switch (reg) {
187b355f08aSPeter Maydell     case 0:
188b355f08aSPeter Maydell         return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPSID]);
189b355f08aSPeter Maydell     case 1:
190b355f08aSPeter Maydell         return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPEXC]);
191b355f08aSPeter Maydell     }
192b355f08aSPeter Maydell     return 0;
193b355f08aSPeter Maydell }
194b355f08aSPeter Maydell 
195b355f08aSPeter Maydell static int vfp_gdb_set_sysreg(CPUARMState *env, uint8_t *buf, int reg)
196b355f08aSPeter Maydell {
197b355f08aSPeter Maydell     switch (reg) {
198b355f08aSPeter Maydell     case 0:
19989f4f20eSPeter Maydell         env->vfp.xregs[ARM_VFP_FPSID] = ldl_p(buf);
20089f4f20eSPeter Maydell         return 4;
20189f4f20eSPeter Maydell     case 1:
20289f4f20eSPeter Maydell         env->vfp.xregs[ARM_VFP_FPEXC] = ldl_p(buf) & (1 << 30);
20389f4f20eSPeter Maydell         return 4;
20489f4f20eSPeter Maydell     }
20589f4f20eSPeter Maydell     return 0;
20689f4f20eSPeter Maydell }
20789f4f20eSPeter Maydell 
208dbd9e084SPeter Maydell static int mve_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg)
209dbd9e084SPeter Maydell {
210dbd9e084SPeter Maydell     switch (reg) {
211dbd9e084SPeter Maydell     case 0:
212dbd9e084SPeter Maydell         return gdb_get_reg32(buf, env->v7m.vpr);
213dbd9e084SPeter Maydell     default:
214dbd9e084SPeter Maydell         return 0;
215dbd9e084SPeter Maydell     }
216dbd9e084SPeter Maydell }
217dbd9e084SPeter Maydell 
218dbd9e084SPeter Maydell static int mve_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
219dbd9e084SPeter Maydell {
220dbd9e084SPeter Maydell     switch (reg) {
221dbd9e084SPeter Maydell     case 0:
222dbd9e084SPeter Maydell         env->v7m.vpr = ldl_p(buf);
223dbd9e084SPeter Maydell         return 4;
224dbd9e084SPeter Maydell     default:
225dbd9e084SPeter Maydell         return 0;
226dbd9e084SPeter Maydell     }
227dbd9e084SPeter Maydell }
228dbd9e084SPeter Maydell 
22989f4f20eSPeter Maydell /**
23089f4f20eSPeter Maydell  * arm_get/set_gdb_*: get/set a gdb register
23189f4f20eSPeter Maydell  * @env: the CPU state
23289f4f20eSPeter Maydell  * @buf: a buffer to copy to/from
23389f4f20eSPeter Maydell  * @reg: register number (offset from start of group)
23489f4f20eSPeter Maydell  *
23589f4f20eSPeter Maydell  * We return the number of bytes copied
23689f4f20eSPeter Maydell  */
23789f4f20eSPeter Maydell 
23889f4f20eSPeter Maydell static int arm_gdb_get_sysreg(CPUARMState *env, GByteArray *buf, int reg)
23989f4f20eSPeter Maydell {
24089f4f20eSPeter Maydell     ARMCPU *cpu = env_archcpu(env);
24189f4f20eSPeter Maydell     const ARMCPRegInfo *ri;
24289f4f20eSPeter Maydell     uint32_t key;
24389f4f20eSPeter Maydell 
24489f4f20eSPeter Maydell     key = cpu->dyn_sysreg_xml.data.cpregs.keys[reg];
24589f4f20eSPeter Maydell     ri = get_arm_cp_reginfo(cpu->cp_regs, key);
24689f4f20eSPeter Maydell     if (ri) {
24789f4f20eSPeter Maydell         if (cpreg_field_is_64bit(ri)) {
24889f4f20eSPeter Maydell             return gdb_get_reg64(buf, (uint64_t)read_raw_cp_reg(env, ri));
24989f4f20eSPeter Maydell         } else {
25089f4f20eSPeter Maydell             return gdb_get_reg32(buf, (uint32_t)read_raw_cp_reg(env, ri));
25189f4f20eSPeter Maydell         }
25289f4f20eSPeter Maydell     }
25389f4f20eSPeter Maydell     return 0;
25489f4f20eSPeter Maydell }
25589f4f20eSPeter Maydell 
25689f4f20eSPeter Maydell static int arm_gdb_set_sysreg(CPUARMState *env, uint8_t *buf, int reg)
25789f4f20eSPeter Maydell {
25889f4f20eSPeter Maydell     return 0;
25989f4f20eSPeter Maydell }
26089f4f20eSPeter Maydell 
261448d4d14SAlex Bennée static void arm_gen_one_xml_sysreg_tag(GString *s, DynamicGDBXMLInfo *dyn_xml,
262200bf5b7SAbdallah Bouassida                                        ARMCPRegInfo *ri, uint32_t ri_key,
26332d6e32aSAlex Bennée                                        int bitsize, int regnum)
264200bf5b7SAbdallah Bouassida {
265200bf5b7SAbdallah Bouassida     g_string_append_printf(s, "<reg name=\"%s\"", ri->name);
266200bf5b7SAbdallah Bouassida     g_string_append_printf(s, " bitsize=\"%d\"", bitsize);
26732d6e32aSAlex Bennée     g_string_append_printf(s, " regnum=\"%d\"", regnum);
268200bf5b7SAbdallah Bouassida     g_string_append_printf(s, " group=\"cp_regs\"/>");
269448d4d14SAlex Bennée     dyn_xml->data.cpregs.keys[dyn_xml->num] = ri_key;
270448d4d14SAlex Bennée     dyn_xml->num++;
271200bf5b7SAbdallah Bouassida }
272200bf5b7SAbdallah Bouassida 
273200bf5b7SAbdallah Bouassida static void arm_register_sysreg_for_xml(gpointer key, gpointer value,
274200bf5b7SAbdallah Bouassida                                         gpointer p)
275200bf5b7SAbdallah Bouassida {
2765860362dSRichard Henderson     uint32_t ri_key = (uintptr_t)key;
277200bf5b7SAbdallah Bouassida     ARMCPRegInfo *ri = value;
278200bf5b7SAbdallah Bouassida     RegisterSysregXmlParam *param = (RegisterSysregXmlParam *)p;
279200bf5b7SAbdallah Bouassida     GString *s = param->s;
280200bf5b7SAbdallah Bouassida     ARMCPU *cpu = ARM_CPU(param->cs);
281200bf5b7SAbdallah Bouassida     CPUARMState *env = &cpu->env;
282448d4d14SAlex Bennée     DynamicGDBXMLInfo *dyn_xml = &cpu->dyn_sysreg_xml;
283200bf5b7SAbdallah Bouassida 
284200bf5b7SAbdallah Bouassida     if (!(ri->type & (ARM_CP_NO_RAW | ARM_CP_NO_GDB))) {
285200bf5b7SAbdallah Bouassida         if (arm_feature(env, ARM_FEATURE_AARCH64)) {
286200bf5b7SAbdallah Bouassida             if (ri->state == ARM_CP_STATE_AA64) {
28732d6e32aSAlex Bennée                 arm_gen_one_xml_sysreg_tag(s , dyn_xml, ri, ri_key, 64,
28832d6e32aSAlex Bennée                                            param->n++);
289200bf5b7SAbdallah Bouassida             }
290200bf5b7SAbdallah Bouassida         } else {
291200bf5b7SAbdallah Bouassida             if (ri->state == ARM_CP_STATE_AA32) {
292200bf5b7SAbdallah Bouassida                 if (!arm_feature(env, ARM_FEATURE_EL3) &&
293200bf5b7SAbdallah Bouassida                     (ri->secure & ARM_CP_SECSTATE_S)) {
294200bf5b7SAbdallah Bouassida                     return;
295200bf5b7SAbdallah Bouassida                 }
296200bf5b7SAbdallah Bouassida                 if (ri->type & ARM_CP_64BIT) {
29732d6e32aSAlex Bennée                     arm_gen_one_xml_sysreg_tag(s , dyn_xml, ri, ri_key, 64,
29832d6e32aSAlex Bennée                                                param->n++);
299200bf5b7SAbdallah Bouassida                 } else {
30032d6e32aSAlex Bennée                     arm_gen_one_xml_sysreg_tag(s , dyn_xml, ri, ri_key, 32,
30132d6e32aSAlex Bennée                                                param->n++);
302200bf5b7SAbdallah Bouassida                 }
303200bf5b7SAbdallah Bouassida             }
304200bf5b7SAbdallah Bouassida         }
305200bf5b7SAbdallah Bouassida     }
306200bf5b7SAbdallah Bouassida }
307200bf5b7SAbdallah Bouassida 
30832d6e32aSAlex Bennée int arm_gen_dynamic_sysreg_xml(CPUState *cs, int base_reg)
309200bf5b7SAbdallah Bouassida {
310200bf5b7SAbdallah Bouassida     ARMCPU *cpu = ARM_CPU(cs);
311200bf5b7SAbdallah Bouassida     GString *s = g_string_new(NULL);
31232d6e32aSAlex Bennée     RegisterSysregXmlParam param = {cs, s, base_reg};
313200bf5b7SAbdallah Bouassida 
314448d4d14SAlex Bennée     cpu->dyn_sysreg_xml.num = 0;
315448d4d14SAlex Bennée     cpu->dyn_sysreg_xml.data.cpregs.keys = g_new(uint32_t, g_hash_table_size(cpu->cp_regs));
316200bf5b7SAbdallah Bouassida     g_string_printf(s, "<?xml version=\"1.0\"?>");
317200bf5b7SAbdallah Bouassida     g_string_append_printf(s, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">");
318200bf5b7SAbdallah Bouassida     g_string_append_printf(s, "<feature name=\"org.qemu.gdb.arm.sys.regs\">");
319200bf5b7SAbdallah Bouassida     g_hash_table_foreach(cpu->cp_regs, arm_register_sysreg_for_xml, &param);
320200bf5b7SAbdallah Bouassida     g_string_append_printf(s, "</feature>");
321448d4d14SAlex Bennée     cpu->dyn_sysreg_xml.desc = g_string_free(s, false);
322448d4d14SAlex Bennée     return cpu->dyn_sysreg_xml.num;
323200bf5b7SAbdallah Bouassida }
324200bf5b7SAbdallah Bouassida 
325d12379c5SAlex Bennée struct TypeSize {
326d12379c5SAlex Bennée     const char *gdb_type;
327d12379c5SAlex Bennée     int  size;
328d12379c5SAlex Bennée     const char sz, suffix;
329d12379c5SAlex Bennée };
330d12379c5SAlex Bennée 
331d12379c5SAlex Bennée static const struct TypeSize vec_lanes[] = {
332d12379c5SAlex Bennée     /* quads */
333d12379c5SAlex Bennée     { "uint128", 128, 'q', 'u' },
334d12379c5SAlex Bennée     { "int128", 128, 'q', 's' },
335d12379c5SAlex Bennée     /* 64 bit */
336797920b9SAlex Bennée     { "ieee_double", 64, 'd', 'f' },
337d12379c5SAlex Bennée     { "uint64", 64, 'd', 'u' },
338d12379c5SAlex Bennée     { "int64", 64, 'd', 's' },
339d12379c5SAlex Bennée     /* 32 bit */
340797920b9SAlex Bennée     { "ieee_single", 32, 's', 'f' },
341d12379c5SAlex Bennée     { "uint32", 32, 's', 'u' },
342d12379c5SAlex Bennée     { "int32", 32, 's', 's' },
343d12379c5SAlex Bennée     /* 16 bit */
344797920b9SAlex Bennée     { "ieee_half", 16, 'h', 'f' },
345d12379c5SAlex Bennée     { "uint16", 16, 'h', 'u' },
346d12379c5SAlex Bennée     { "int16", 16, 'h', 's' },
347d12379c5SAlex Bennée     /* bytes */
348d12379c5SAlex Bennée     { "uint8", 8, 'b', 'u' },
349d12379c5SAlex Bennée     { "int8", 8, 'b', 's' },
350d12379c5SAlex Bennée };
351d12379c5SAlex Bennée 
352d12379c5SAlex Bennée 
353d12379c5SAlex Bennée int arm_gen_dynamic_svereg_xml(CPUState *cs, int base_reg)
354d12379c5SAlex Bennée {
355d12379c5SAlex Bennée     ARMCPU *cpu = ARM_CPU(cs);
356d12379c5SAlex Bennée     GString *s = g_string_new(NULL);
357d12379c5SAlex Bennée     DynamicGDBXMLInfo *info = &cpu->dyn_svereg_xml;
358d12379c5SAlex Bennée     g_autoptr(GString) ts = g_string_new("");
359797920b9SAlex Bennée     int i, j, bits, reg_width = (cpu->sve_max_vq * 128);
360d12379c5SAlex Bennée     info->num = 0;
361d12379c5SAlex Bennée     g_string_printf(s, "<?xml version=\"1.0\"?>");
362d12379c5SAlex Bennée     g_string_append_printf(s, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">");
363797920b9SAlex Bennée     g_string_append_printf(s, "<feature name=\"org.gnu.gdb.aarch64.sve\">");
364d12379c5SAlex Bennée 
365d12379c5SAlex Bennée     /* First define types and totals in a whole VL */
366d12379c5SAlex Bennée     for (i = 0; i < ARRAY_SIZE(vec_lanes); i++) {
367d12379c5SAlex Bennée         int count = reg_width / vec_lanes[i].size;
368797920b9SAlex Bennée         g_string_printf(ts, "svev%c%c", vec_lanes[i].sz, vec_lanes[i].suffix);
369d12379c5SAlex Bennée         g_string_append_printf(s,
370d12379c5SAlex Bennée                                "<vector id=\"%s\" type=\"%s\" count=\"%d\"/>",
371d12379c5SAlex Bennée                                ts->str, vec_lanes[i].gdb_type, count);
372d12379c5SAlex Bennée     }
373d12379c5SAlex Bennée     /*
374d12379c5SAlex Bennée      * Now define a union for each size group containing unsigned and
375d12379c5SAlex Bennée      * signed and potentially float versions of each size from 128 to
376d12379c5SAlex Bennée      * 8 bits.
377d12379c5SAlex Bennée      */
378797920b9SAlex Bennée     for (bits = 128, i = 0; bits >= 8; bits /= 2, i++) {
379797920b9SAlex Bennée         const char suf[] = { 'q', 'd', 's', 'h', 'b' };
380797920b9SAlex Bennée         g_string_append_printf(s, "<union id=\"svevn%c\">", suf[i]);
381797920b9SAlex Bennée         for (j = 0; j < ARRAY_SIZE(vec_lanes); j++) {
382797920b9SAlex Bennée             if (vec_lanes[j].size == bits) {
383797920b9SAlex Bennée                 g_string_append_printf(s, "<field name=\"%c\" type=\"svev%c%c\"/>",
384797920b9SAlex Bennée                                        vec_lanes[j].suffix,
385797920b9SAlex Bennée                                        vec_lanes[j].sz, vec_lanes[j].suffix);
386d12379c5SAlex Bennée             }
387d12379c5SAlex Bennée         }
388d12379c5SAlex Bennée         g_string_append(s, "</union>");
389d12379c5SAlex Bennée     }
390d12379c5SAlex Bennée     /* And now the final union of unions */
391797920b9SAlex Bennée     g_string_append(s, "<union id=\"svev\">");
392797920b9SAlex Bennée     for (bits = 128, i = 0; bits >= 8; bits /= 2, i++) {
393797920b9SAlex Bennée         const char suf[] = { 'q', 'd', 's', 'h', 'b' };
394797920b9SAlex Bennée         g_string_append_printf(s, "<field name=\"%c\" type=\"svevn%c\"/>",
395797920b9SAlex Bennée                                suf[i], suf[i]);
396d12379c5SAlex Bennée     }
397d12379c5SAlex Bennée     g_string_append(s, "</union>");
398d12379c5SAlex Bennée 
399797920b9SAlex Bennée     /* Finally the sve prefix type */
400797920b9SAlex Bennée     g_string_append_printf(s,
401797920b9SAlex Bennée                            "<vector id=\"svep\" type=\"uint8\" count=\"%d\"/>",
402797920b9SAlex Bennée                            reg_width / 8);
403797920b9SAlex Bennée 
404d12379c5SAlex Bennée     /* Then define each register in parts for each vq */
405d12379c5SAlex Bennée     for (i = 0; i < 32; i++) {
406d12379c5SAlex Bennée         g_string_append_printf(s,
407d12379c5SAlex Bennée                                "<reg name=\"z%d\" bitsize=\"%d\""
408797920b9SAlex Bennée                                " regnum=\"%d\" type=\"svev\"/>",
409d12379c5SAlex Bennée                                i, reg_width, base_reg++);
410d12379c5SAlex Bennée         info->num++;
411d12379c5SAlex Bennée     }
412d12379c5SAlex Bennée     /* fpscr & status registers */
413d12379c5SAlex Bennée     g_string_append_printf(s, "<reg name=\"fpsr\" bitsize=\"32\""
414d12379c5SAlex Bennée                            " regnum=\"%d\" group=\"float\""
415d12379c5SAlex Bennée                            " type=\"int\"/>", base_reg++);
416d12379c5SAlex Bennée     g_string_append_printf(s, "<reg name=\"fpcr\" bitsize=\"32\""
417d12379c5SAlex Bennée                            " regnum=\"%d\" group=\"float\""
418d12379c5SAlex Bennée                            " type=\"int\"/>", base_reg++);
419d12379c5SAlex Bennée     info->num += 2;
420797920b9SAlex Bennée 
421d12379c5SAlex Bennée     for (i = 0; i < 16; i++) {
422d12379c5SAlex Bennée         g_string_append_printf(s,
423d12379c5SAlex Bennée                                "<reg name=\"p%d\" bitsize=\"%d\""
424797920b9SAlex Bennée                                " regnum=\"%d\" type=\"svep\"/>",
425d12379c5SAlex Bennée                                i, cpu->sve_max_vq * 16, base_reg++);
426d12379c5SAlex Bennée         info->num++;
427d12379c5SAlex Bennée     }
428d12379c5SAlex Bennée     g_string_append_printf(s,
429d12379c5SAlex Bennée                            "<reg name=\"ffr\" bitsize=\"%d\""
430d12379c5SAlex Bennée                            " regnum=\"%d\" group=\"vector\""
431797920b9SAlex Bennée                            " type=\"svep\"/>",
432d12379c5SAlex Bennée                            cpu->sve_max_vq * 16, base_reg++);
433d12379c5SAlex Bennée     g_string_append_printf(s,
434d12379c5SAlex Bennée                            "<reg name=\"vg\" bitsize=\"64\""
435797920b9SAlex Bennée                            " regnum=\"%d\" type=\"int\"/>",
436d12379c5SAlex Bennée                            base_reg++);
437d12379c5SAlex Bennée     info->num += 2;
438d12379c5SAlex Bennée     g_string_append_printf(s, "</feature>");
439d12379c5SAlex Bennée     cpu->dyn_svereg_xml.desc = g_string_free(s, false);
440d12379c5SAlex Bennée 
441d12379c5SAlex Bennée     return cpu->dyn_svereg_xml.num;
442d12379c5SAlex Bennée }
443d12379c5SAlex Bennée 
444d12379c5SAlex Bennée 
445200bf5b7SAbdallah Bouassida const char *arm_gdb_get_dynamic_xml(CPUState *cs, const char *xmlname)
446200bf5b7SAbdallah Bouassida {
447200bf5b7SAbdallah Bouassida     ARMCPU *cpu = ARM_CPU(cs);
448200bf5b7SAbdallah Bouassida 
449200bf5b7SAbdallah Bouassida     if (strcmp(xmlname, "system-registers.xml") == 0) {
450448d4d14SAlex Bennée         return cpu->dyn_sysreg_xml.desc;
451d12379c5SAlex Bennée     } else if (strcmp(xmlname, "sve-registers.xml") == 0) {
452d12379c5SAlex Bennée         return cpu->dyn_svereg_xml.desc;
453200bf5b7SAbdallah Bouassida     }
454200bf5b7SAbdallah Bouassida     return NULL;
455200bf5b7SAbdallah Bouassida }
45689f4f20eSPeter Maydell 
45789f4f20eSPeter Maydell void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
45889f4f20eSPeter Maydell {
45989f4f20eSPeter Maydell     CPUState *cs = CPU(cpu);
46089f4f20eSPeter Maydell     CPUARMState *env = &cpu->env;
46189f4f20eSPeter Maydell 
46289f4f20eSPeter Maydell     if (arm_feature(env, ARM_FEATURE_AARCH64)) {
46389f4f20eSPeter Maydell         /*
46489f4f20eSPeter Maydell          * The lower part of each SVE register aliases to the FPU
46589f4f20eSPeter Maydell          * registers so we don't need to include both.
46689f4f20eSPeter Maydell          */
46789f4f20eSPeter Maydell #ifdef TARGET_AARCH64
46889f4f20eSPeter Maydell         if (isar_feature_aa64_sve(&cpu->isar)) {
469*963a6b91SRichard Henderson             int nreg = arm_gen_dynamic_svereg_xml(cs, cs->gdb_num_regs);
470*963a6b91SRichard Henderson             gdb_register_coprocessor(cs, aarch64_gdb_get_sve_reg,
471*963a6b91SRichard Henderson                                      aarch64_gdb_set_sve_reg, nreg,
47289f4f20eSPeter Maydell                                      "sve-registers.xml", 0);
47389f4f20eSPeter Maydell         } else {
474*963a6b91SRichard Henderson             gdb_register_coprocessor(cs, aarch64_gdb_get_fpu_reg,
475*963a6b91SRichard Henderson                                      aarch64_gdb_set_fpu_reg,
47689f4f20eSPeter Maydell                                      34, "aarch64-fpu.xml", 0);
47789f4f20eSPeter Maydell         }
47889f4f20eSPeter Maydell #endif
479b355f08aSPeter Maydell     } else {
480b355f08aSPeter Maydell         if (arm_feature(env, ARM_FEATURE_NEON)) {
48189f4f20eSPeter Maydell             gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
482b355f08aSPeter Maydell                                      49, "arm-neon.xml", 0);
48389f4f20eSPeter Maydell         } else if (cpu_isar_feature(aa32_simd_r32, cpu)) {
48489f4f20eSPeter Maydell             gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
485b355f08aSPeter Maydell                                      33, "arm-vfp3.xml", 0);
48689f4f20eSPeter Maydell         } else if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
48789f4f20eSPeter Maydell             gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
488b355f08aSPeter Maydell                                      17, "arm-vfp.xml", 0);
489b355f08aSPeter Maydell         }
490b355f08aSPeter Maydell         if (!arm_feature(env, ARM_FEATURE_M)) {
491b355f08aSPeter Maydell             /*
492b355f08aSPeter Maydell              * A and R profile have FP sysregs FPEXC and FPSID that we
493b355f08aSPeter Maydell              * expose to gdb.
494b355f08aSPeter Maydell              */
495b355f08aSPeter Maydell             gdb_register_coprocessor(cs, vfp_gdb_get_sysreg, vfp_gdb_set_sysreg,
496b355f08aSPeter Maydell                                      2, "arm-vfp-sysregs.xml", 0);
497b355f08aSPeter Maydell         }
49889f4f20eSPeter Maydell     }
499dbd9e084SPeter Maydell     if (cpu_isar_feature(aa32_mve, cpu)) {
500dbd9e084SPeter Maydell         gdb_register_coprocessor(cs, mve_gdb_get_reg, mve_gdb_set_reg,
501dbd9e084SPeter Maydell                                  1, "arm-m-profile-mve.xml", 0);
502dbd9e084SPeter Maydell     }
50389f4f20eSPeter Maydell     gdb_register_coprocessor(cs, arm_gdb_get_sysreg, arm_gdb_set_sysreg,
50489f4f20eSPeter Maydell                              arm_gen_dynamic_sysreg_xml(cs, cs->gdb_num_regs),
50589f4f20eSPeter Maydell                              "system-registers.xml", 0);
50689f4f20eSPeter Maydell 
50789f4f20eSPeter Maydell }
508