xref: /openbmc/qemu/target/arm/gdbstub.c (revision dbd9e08476f09cf3556b9b8a306bf277172841a9)
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"
2289f4f20eSPeter 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 
12889f4f20eSPeter Maydell static int vfp_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg)
12989f4f20eSPeter Maydell {
13089f4f20eSPeter Maydell     ARMCPU *cpu = env_archcpu(env);
13189f4f20eSPeter Maydell     int nregs = cpu_isar_feature(aa32_simd_r32, cpu) ? 32 : 16;
13289f4f20eSPeter Maydell 
13389f4f20eSPeter Maydell     /* VFP data registers are always little-endian.  */
13489f4f20eSPeter Maydell     if (reg < nregs) {
13589f4f20eSPeter Maydell         return gdb_get_reg64(buf, *aa32_vfp_dreg(env, reg));
13689f4f20eSPeter Maydell     }
13789f4f20eSPeter Maydell     if (arm_feature(env, ARM_FEATURE_NEON)) {
13889f4f20eSPeter Maydell         /* Aliases for Q regs.  */
13989f4f20eSPeter Maydell         nregs += 16;
14089f4f20eSPeter Maydell         if (reg < nregs) {
14189f4f20eSPeter Maydell             uint64_t *q = aa32_vfp_qreg(env, reg - 32);
14289f4f20eSPeter Maydell             return gdb_get_reg128(buf, q[0], q[1]);
14389f4f20eSPeter Maydell         }
14489f4f20eSPeter Maydell     }
14589f4f20eSPeter Maydell     switch (reg - nregs) {
14689f4f20eSPeter Maydell     case 0:
14789f4f20eSPeter Maydell         return gdb_get_reg32(buf, vfp_get_fpscr(env));
14889f4f20eSPeter Maydell     }
14989f4f20eSPeter Maydell     return 0;
15089f4f20eSPeter Maydell }
15189f4f20eSPeter Maydell 
15289f4f20eSPeter Maydell static int vfp_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
15389f4f20eSPeter Maydell {
15489f4f20eSPeter Maydell     ARMCPU *cpu = env_archcpu(env);
15589f4f20eSPeter Maydell     int nregs = cpu_isar_feature(aa32_simd_r32, cpu) ? 32 : 16;
15689f4f20eSPeter Maydell 
15789f4f20eSPeter Maydell     if (reg < nregs) {
15889f4f20eSPeter Maydell         *aa32_vfp_dreg(env, reg) = ldq_le_p(buf);
15989f4f20eSPeter Maydell         return 8;
16089f4f20eSPeter Maydell     }
16189f4f20eSPeter Maydell     if (arm_feature(env, ARM_FEATURE_NEON)) {
16289f4f20eSPeter Maydell         nregs += 16;
16389f4f20eSPeter Maydell         if (reg < nregs) {
16489f4f20eSPeter Maydell             uint64_t *q = aa32_vfp_qreg(env, reg - 32);
16589f4f20eSPeter Maydell             q[0] = ldq_le_p(buf);
16689f4f20eSPeter Maydell             q[1] = ldq_le_p(buf + 8);
16789f4f20eSPeter Maydell             return 16;
16889f4f20eSPeter Maydell         }
16989f4f20eSPeter Maydell     }
17089f4f20eSPeter Maydell     switch (reg - nregs) {
17189f4f20eSPeter Maydell     case 0:
172b355f08aSPeter Maydell         vfp_set_fpscr(env, ldl_p(buf));
173b355f08aSPeter Maydell         return 4;
174b355f08aSPeter Maydell     }
175b355f08aSPeter Maydell     return 0;
176b355f08aSPeter Maydell }
177b355f08aSPeter Maydell 
178b355f08aSPeter Maydell static int vfp_gdb_get_sysreg(CPUARMState *env, GByteArray *buf, int reg)
179b355f08aSPeter Maydell {
180b355f08aSPeter Maydell     switch (reg) {
181b355f08aSPeter Maydell     case 0:
182b355f08aSPeter Maydell         return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPSID]);
183b355f08aSPeter Maydell     case 1:
184b355f08aSPeter Maydell         return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPEXC]);
185b355f08aSPeter Maydell     }
186b355f08aSPeter Maydell     return 0;
187b355f08aSPeter Maydell }
188b355f08aSPeter Maydell 
189b355f08aSPeter Maydell static int vfp_gdb_set_sysreg(CPUARMState *env, uint8_t *buf, int reg)
190b355f08aSPeter Maydell {
191b355f08aSPeter Maydell     switch (reg) {
192b355f08aSPeter Maydell     case 0:
19389f4f20eSPeter Maydell         env->vfp.xregs[ARM_VFP_FPSID] = ldl_p(buf);
19489f4f20eSPeter Maydell         return 4;
19589f4f20eSPeter Maydell     case 1:
19689f4f20eSPeter Maydell         env->vfp.xregs[ARM_VFP_FPEXC] = ldl_p(buf) & (1 << 30);
19789f4f20eSPeter Maydell         return 4;
19889f4f20eSPeter Maydell     }
19989f4f20eSPeter Maydell     return 0;
20089f4f20eSPeter Maydell }
20189f4f20eSPeter Maydell 
202*dbd9e084SPeter Maydell static int mve_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg)
203*dbd9e084SPeter Maydell {
204*dbd9e084SPeter Maydell     switch (reg) {
205*dbd9e084SPeter Maydell     case 0:
206*dbd9e084SPeter Maydell         return gdb_get_reg32(buf, env->v7m.vpr);
207*dbd9e084SPeter Maydell     default:
208*dbd9e084SPeter Maydell         return 0;
209*dbd9e084SPeter Maydell     }
210*dbd9e084SPeter Maydell }
211*dbd9e084SPeter Maydell 
212*dbd9e084SPeter Maydell static int mve_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
213*dbd9e084SPeter Maydell {
214*dbd9e084SPeter Maydell     switch (reg) {
215*dbd9e084SPeter Maydell     case 0:
216*dbd9e084SPeter Maydell         env->v7m.vpr = ldl_p(buf);
217*dbd9e084SPeter Maydell         return 4;
218*dbd9e084SPeter Maydell     default:
219*dbd9e084SPeter Maydell         return 0;
220*dbd9e084SPeter Maydell     }
221*dbd9e084SPeter Maydell }
222*dbd9e084SPeter Maydell 
22389f4f20eSPeter Maydell /**
22489f4f20eSPeter Maydell  * arm_get/set_gdb_*: get/set a gdb register
22589f4f20eSPeter Maydell  * @env: the CPU state
22689f4f20eSPeter Maydell  * @buf: a buffer to copy to/from
22789f4f20eSPeter Maydell  * @reg: register number (offset from start of group)
22889f4f20eSPeter Maydell  *
22989f4f20eSPeter Maydell  * We return the number of bytes copied
23089f4f20eSPeter Maydell  */
23189f4f20eSPeter Maydell 
23289f4f20eSPeter Maydell static int arm_gdb_get_sysreg(CPUARMState *env, GByteArray *buf, int reg)
23389f4f20eSPeter Maydell {
23489f4f20eSPeter Maydell     ARMCPU *cpu = env_archcpu(env);
23589f4f20eSPeter Maydell     const ARMCPRegInfo *ri;
23689f4f20eSPeter Maydell     uint32_t key;
23789f4f20eSPeter Maydell 
23889f4f20eSPeter Maydell     key = cpu->dyn_sysreg_xml.data.cpregs.keys[reg];
23989f4f20eSPeter Maydell     ri = get_arm_cp_reginfo(cpu->cp_regs, key);
24089f4f20eSPeter Maydell     if (ri) {
24189f4f20eSPeter Maydell         if (cpreg_field_is_64bit(ri)) {
24289f4f20eSPeter Maydell             return gdb_get_reg64(buf, (uint64_t)read_raw_cp_reg(env, ri));
24389f4f20eSPeter Maydell         } else {
24489f4f20eSPeter Maydell             return gdb_get_reg32(buf, (uint32_t)read_raw_cp_reg(env, ri));
24589f4f20eSPeter Maydell         }
24689f4f20eSPeter Maydell     }
24789f4f20eSPeter Maydell     return 0;
24889f4f20eSPeter Maydell }
24989f4f20eSPeter Maydell 
25089f4f20eSPeter Maydell static int arm_gdb_set_sysreg(CPUARMState *env, uint8_t *buf, int reg)
25189f4f20eSPeter Maydell {
25289f4f20eSPeter Maydell     return 0;
25389f4f20eSPeter Maydell }
25489f4f20eSPeter Maydell 
255448d4d14SAlex Bennée static void arm_gen_one_xml_sysreg_tag(GString *s, DynamicGDBXMLInfo *dyn_xml,
256200bf5b7SAbdallah Bouassida                                        ARMCPRegInfo *ri, uint32_t ri_key,
25732d6e32aSAlex Bennée                                        int bitsize, int regnum)
258200bf5b7SAbdallah Bouassida {
259200bf5b7SAbdallah Bouassida     g_string_append_printf(s, "<reg name=\"%s\"", ri->name);
260200bf5b7SAbdallah Bouassida     g_string_append_printf(s, " bitsize=\"%d\"", bitsize);
26132d6e32aSAlex Bennée     g_string_append_printf(s, " regnum=\"%d\"", regnum);
262200bf5b7SAbdallah Bouassida     g_string_append_printf(s, " group=\"cp_regs\"/>");
263448d4d14SAlex Bennée     dyn_xml->data.cpregs.keys[dyn_xml->num] = ri_key;
264448d4d14SAlex Bennée     dyn_xml->num++;
265200bf5b7SAbdallah Bouassida }
266200bf5b7SAbdallah Bouassida 
267200bf5b7SAbdallah Bouassida static void arm_register_sysreg_for_xml(gpointer key, gpointer value,
268200bf5b7SAbdallah Bouassida                                         gpointer p)
269200bf5b7SAbdallah Bouassida {
270200bf5b7SAbdallah Bouassida     uint32_t ri_key = *(uint32_t *)key;
271200bf5b7SAbdallah Bouassida     ARMCPRegInfo *ri = value;
272200bf5b7SAbdallah Bouassida     RegisterSysregXmlParam *param = (RegisterSysregXmlParam *)p;
273200bf5b7SAbdallah Bouassida     GString *s = param->s;
274200bf5b7SAbdallah Bouassida     ARMCPU *cpu = ARM_CPU(param->cs);
275200bf5b7SAbdallah Bouassida     CPUARMState *env = &cpu->env;
276448d4d14SAlex Bennée     DynamicGDBXMLInfo *dyn_xml = &cpu->dyn_sysreg_xml;
277200bf5b7SAbdallah Bouassida 
278200bf5b7SAbdallah Bouassida     if (!(ri->type & (ARM_CP_NO_RAW | ARM_CP_NO_GDB))) {
279200bf5b7SAbdallah Bouassida         if (arm_feature(env, ARM_FEATURE_AARCH64)) {
280200bf5b7SAbdallah Bouassida             if (ri->state == ARM_CP_STATE_AA64) {
28132d6e32aSAlex Bennée                 arm_gen_one_xml_sysreg_tag(s , dyn_xml, ri, ri_key, 64,
28232d6e32aSAlex Bennée                                            param->n++);
283200bf5b7SAbdallah Bouassida             }
284200bf5b7SAbdallah Bouassida         } else {
285200bf5b7SAbdallah Bouassida             if (ri->state == ARM_CP_STATE_AA32) {
286200bf5b7SAbdallah Bouassida                 if (!arm_feature(env, ARM_FEATURE_EL3) &&
287200bf5b7SAbdallah Bouassida                     (ri->secure & ARM_CP_SECSTATE_S)) {
288200bf5b7SAbdallah Bouassida                     return;
289200bf5b7SAbdallah Bouassida                 }
290200bf5b7SAbdallah Bouassida                 if (ri->type & ARM_CP_64BIT) {
29132d6e32aSAlex Bennée                     arm_gen_one_xml_sysreg_tag(s , dyn_xml, ri, ri_key, 64,
29232d6e32aSAlex Bennée                                                param->n++);
293200bf5b7SAbdallah Bouassida                 } else {
29432d6e32aSAlex Bennée                     arm_gen_one_xml_sysreg_tag(s , dyn_xml, ri, ri_key, 32,
29532d6e32aSAlex Bennée                                                param->n++);
296200bf5b7SAbdallah Bouassida                 }
297200bf5b7SAbdallah Bouassida             }
298200bf5b7SAbdallah Bouassida         }
299200bf5b7SAbdallah Bouassida     }
300200bf5b7SAbdallah Bouassida }
301200bf5b7SAbdallah Bouassida 
30232d6e32aSAlex Bennée int arm_gen_dynamic_sysreg_xml(CPUState *cs, int base_reg)
303200bf5b7SAbdallah Bouassida {
304200bf5b7SAbdallah Bouassida     ARMCPU *cpu = ARM_CPU(cs);
305200bf5b7SAbdallah Bouassida     GString *s = g_string_new(NULL);
30632d6e32aSAlex Bennée     RegisterSysregXmlParam param = {cs, s, base_reg};
307200bf5b7SAbdallah Bouassida 
308448d4d14SAlex Bennée     cpu->dyn_sysreg_xml.num = 0;
309448d4d14SAlex Bennée     cpu->dyn_sysreg_xml.data.cpregs.keys = g_new(uint32_t, g_hash_table_size(cpu->cp_regs));
310200bf5b7SAbdallah Bouassida     g_string_printf(s, "<?xml version=\"1.0\"?>");
311200bf5b7SAbdallah Bouassida     g_string_append_printf(s, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">");
312200bf5b7SAbdallah Bouassida     g_string_append_printf(s, "<feature name=\"org.qemu.gdb.arm.sys.regs\">");
313200bf5b7SAbdallah Bouassida     g_hash_table_foreach(cpu->cp_regs, arm_register_sysreg_for_xml, &param);
314200bf5b7SAbdallah Bouassida     g_string_append_printf(s, "</feature>");
315448d4d14SAlex Bennée     cpu->dyn_sysreg_xml.desc = g_string_free(s, false);
316448d4d14SAlex Bennée     return cpu->dyn_sysreg_xml.num;
317200bf5b7SAbdallah Bouassida }
318200bf5b7SAbdallah Bouassida 
319d12379c5SAlex Bennée struct TypeSize {
320d12379c5SAlex Bennée     const char *gdb_type;
321d12379c5SAlex Bennée     int  size;
322d12379c5SAlex Bennée     const char sz, suffix;
323d12379c5SAlex Bennée };
324d12379c5SAlex Bennée 
325d12379c5SAlex Bennée static const struct TypeSize vec_lanes[] = {
326d12379c5SAlex Bennée     /* quads */
327d12379c5SAlex Bennée     { "uint128", 128, 'q', 'u' },
328d12379c5SAlex Bennée     { "int128", 128, 'q', 's' },
329d12379c5SAlex Bennée     /* 64 bit */
330797920b9SAlex Bennée     { "ieee_double", 64, 'd', 'f' },
331d12379c5SAlex Bennée     { "uint64", 64, 'd', 'u' },
332d12379c5SAlex Bennée     { "int64", 64, 'd', 's' },
333d12379c5SAlex Bennée     /* 32 bit */
334797920b9SAlex Bennée     { "ieee_single", 32, 's', 'f' },
335d12379c5SAlex Bennée     { "uint32", 32, 's', 'u' },
336d12379c5SAlex Bennée     { "int32", 32, 's', 's' },
337d12379c5SAlex Bennée     /* 16 bit */
338797920b9SAlex Bennée     { "ieee_half", 16, 'h', 'f' },
339d12379c5SAlex Bennée     { "uint16", 16, 'h', 'u' },
340d12379c5SAlex Bennée     { "int16", 16, 'h', 's' },
341d12379c5SAlex Bennée     /* bytes */
342d12379c5SAlex Bennée     { "uint8", 8, 'b', 'u' },
343d12379c5SAlex Bennée     { "int8", 8, 'b', 's' },
344d12379c5SAlex Bennée };
345d12379c5SAlex Bennée 
346d12379c5SAlex Bennée 
347d12379c5SAlex Bennée int arm_gen_dynamic_svereg_xml(CPUState *cs, int base_reg)
348d12379c5SAlex Bennée {
349d12379c5SAlex Bennée     ARMCPU *cpu = ARM_CPU(cs);
350d12379c5SAlex Bennée     GString *s = g_string_new(NULL);
351d12379c5SAlex Bennée     DynamicGDBXMLInfo *info = &cpu->dyn_svereg_xml;
352d12379c5SAlex Bennée     g_autoptr(GString) ts = g_string_new("");
353797920b9SAlex Bennée     int i, j, bits, reg_width = (cpu->sve_max_vq * 128);
354d12379c5SAlex Bennée     info->num = 0;
355d12379c5SAlex Bennée     g_string_printf(s, "<?xml version=\"1.0\"?>");
356d12379c5SAlex Bennée     g_string_append_printf(s, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">");
357797920b9SAlex Bennée     g_string_append_printf(s, "<feature name=\"org.gnu.gdb.aarch64.sve\">");
358d12379c5SAlex Bennée 
359d12379c5SAlex Bennée     /* First define types and totals in a whole VL */
360d12379c5SAlex Bennée     for (i = 0; i < ARRAY_SIZE(vec_lanes); i++) {
361d12379c5SAlex Bennée         int count = reg_width / vec_lanes[i].size;
362797920b9SAlex Bennée         g_string_printf(ts, "svev%c%c", vec_lanes[i].sz, vec_lanes[i].suffix);
363d12379c5SAlex Bennée         g_string_append_printf(s,
364d12379c5SAlex Bennée                                "<vector id=\"%s\" type=\"%s\" count=\"%d\"/>",
365d12379c5SAlex Bennée                                ts->str, vec_lanes[i].gdb_type, count);
366d12379c5SAlex Bennée     }
367d12379c5SAlex Bennée     /*
368d12379c5SAlex Bennée      * Now define a union for each size group containing unsigned and
369d12379c5SAlex Bennée      * signed and potentially float versions of each size from 128 to
370d12379c5SAlex Bennée      * 8 bits.
371d12379c5SAlex Bennée      */
372797920b9SAlex Bennée     for (bits = 128, i = 0; bits >= 8; bits /= 2, i++) {
373797920b9SAlex Bennée         const char suf[] = { 'q', 'd', 's', 'h', 'b' };
374797920b9SAlex Bennée         g_string_append_printf(s, "<union id=\"svevn%c\">", suf[i]);
375797920b9SAlex Bennée         for (j = 0; j < ARRAY_SIZE(vec_lanes); j++) {
376797920b9SAlex Bennée             if (vec_lanes[j].size == bits) {
377797920b9SAlex Bennée                 g_string_append_printf(s, "<field name=\"%c\" type=\"svev%c%c\"/>",
378797920b9SAlex Bennée                                        vec_lanes[j].suffix,
379797920b9SAlex Bennée                                        vec_lanes[j].sz, vec_lanes[j].suffix);
380d12379c5SAlex Bennée             }
381d12379c5SAlex Bennée         }
382d12379c5SAlex Bennée         g_string_append(s, "</union>");
383d12379c5SAlex Bennée     }
384d12379c5SAlex Bennée     /* And now the final union of unions */
385797920b9SAlex Bennée     g_string_append(s, "<union id=\"svev\">");
386797920b9SAlex Bennée     for (bits = 128, i = 0; bits >= 8; bits /= 2, i++) {
387797920b9SAlex Bennée         const char suf[] = { 'q', 'd', 's', 'h', 'b' };
388797920b9SAlex Bennée         g_string_append_printf(s, "<field name=\"%c\" type=\"svevn%c\"/>",
389797920b9SAlex Bennée                                suf[i], suf[i]);
390d12379c5SAlex Bennée     }
391d12379c5SAlex Bennée     g_string_append(s, "</union>");
392d12379c5SAlex Bennée 
393797920b9SAlex Bennée     /* Finally the sve prefix type */
394797920b9SAlex Bennée     g_string_append_printf(s,
395797920b9SAlex Bennée                            "<vector id=\"svep\" type=\"uint8\" count=\"%d\"/>",
396797920b9SAlex Bennée                            reg_width / 8);
397797920b9SAlex Bennée 
398d12379c5SAlex Bennée     /* Then define each register in parts for each vq */
399d12379c5SAlex Bennée     for (i = 0; i < 32; i++) {
400d12379c5SAlex Bennée         g_string_append_printf(s,
401d12379c5SAlex Bennée                                "<reg name=\"z%d\" bitsize=\"%d\""
402797920b9SAlex Bennée                                " regnum=\"%d\" type=\"svev\"/>",
403d12379c5SAlex Bennée                                i, reg_width, base_reg++);
404d12379c5SAlex Bennée         info->num++;
405d12379c5SAlex Bennée     }
406d12379c5SAlex Bennée     /* fpscr & status registers */
407d12379c5SAlex Bennée     g_string_append_printf(s, "<reg name=\"fpsr\" bitsize=\"32\""
408d12379c5SAlex Bennée                            " regnum=\"%d\" group=\"float\""
409d12379c5SAlex Bennée                            " type=\"int\"/>", base_reg++);
410d12379c5SAlex Bennée     g_string_append_printf(s, "<reg name=\"fpcr\" bitsize=\"32\""
411d12379c5SAlex Bennée                            " regnum=\"%d\" group=\"float\""
412d12379c5SAlex Bennée                            " type=\"int\"/>", base_reg++);
413d12379c5SAlex Bennée     info->num += 2;
414797920b9SAlex Bennée 
415d12379c5SAlex Bennée     for (i = 0; i < 16; i++) {
416d12379c5SAlex Bennée         g_string_append_printf(s,
417d12379c5SAlex Bennée                                "<reg name=\"p%d\" bitsize=\"%d\""
418797920b9SAlex Bennée                                " regnum=\"%d\" type=\"svep\"/>",
419d12379c5SAlex Bennée                                i, cpu->sve_max_vq * 16, base_reg++);
420d12379c5SAlex Bennée         info->num++;
421d12379c5SAlex Bennée     }
422d12379c5SAlex Bennée     g_string_append_printf(s,
423d12379c5SAlex Bennée                            "<reg name=\"ffr\" bitsize=\"%d\""
424d12379c5SAlex Bennée                            " regnum=\"%d\" group=\"vector\""
425797920b9SAlex Bennée                            " type=\"svep\"/>",
426d12379c5SAlex Bennée                            cpu->sve_max_vq * 16, base_reg++);
427d12379c5SAlex Bennée     g_string_append_printf(s,
428d12379c5SAlex Bennée                            "<reg name=\"vg\" bitsize=\"64\""
429797920b9SAlex Bennée                            " regnum=\"%d\" type=\"int\"/>",
430d12379c5SAlex Bennée                            base_reg++);
431d12379c5SAlex Bennée     info->num += 2;
432d12379c5SAlex Bennée     g_string_append_printf(s, "</feature>");
433d12379c5SAlex Bennée     cpu->dyn_svereg_xml.desc = g_string_free(s, false);
434d12379c5SAlex Bennée 
435d12379c5SAlex Bennée     return cpu->dyn_svereg_xml.num;
436d12379c5SAlex Bennée }
437d12379c5SAlex Bennée 
438d12379c5SAlex Bennée 
439200bf5b7SAbdallah Bouassida const char *arm_gdb_get_dynamic_xml(CPUState *cs, const char *xmlname)
440200bf5b7SAbdallah Bouassida {
441200bf5b7SAbdallah Bouassida     ARMCPU *cpu = ARM_CPU(cs);
442200bf5b7SAbdallah Bouassida 
443200bf5b7SAbdallah Bouassida     if (strcmp(xmlname, "system-registers.xml") == 0) {
444448d4d14SAlex Bennée         return cpu->dyn_sysreg_xml.desc;
445d12379c5SAlex Bennée     } else if (strcmp(xmlname, "sve-registers.xml") == 0) {
446d12379c5SAlex Bennée         return cpu->dyn_svereg_xml.desc;
447200bf5b7SAbdallah Bouassida     }
448200bf5b7SAbdallah Bouassida     return NULL;
449200bf5b7SAbdallah Bouassida }
45089f4f20eSPeter Maydell 
45189f4f20eSPeter Maydell void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
45289f4f20eSPeter Maydell {
45389f4f20eSPeter Maydell     CPUState *cs = CPU(cpu);
45489f4f20eSPeter Maydell     CPUARMState *env = &cpu->env;
45589f4f20eSPeter Maydell 
45689f4f20eSPeter Maydell     if (arm_feature(env, ARM_FEATURE_AARCH64)) {
45789f4f20eSPeter Maydell         /*
45889f4f20eSPeter Maydell          * The lower part of each SVE register aliases to the FPU
45989f4f20eSPeter Maydell          * registers so we don't need to include both.
46089f4f20eSPeter Maydell          */
46189f4f20eSPeter Maydell #ifdef TARGET_AARCH64
46289f4f20eSPeter Maydell         if (isar_feature_aa64_sve(&cpu->isar)) {
46389f4f20eSPeter Maydell             gdb_register_coprocessor(cs, arm_gdb_get_svereg, arm_gdb_set_svereg,
46489f4f20eSPeter Maydell                                      arm_gen_dynamic_svereg_xml(cs, cs->gdb_num_regs),
46589f4f20eSPeter Maydell                                      "sve-registers.xml", 0);
46689f4f20eSPeter Maydell         } else {
46789f4f20eSPeter Maydell             gdb_register_coprocessor(cs, aarch64_fpu_gdb_get_reg,
46889f4f20eSPeter Maydell                                      aarch64_fpu_gdb_set_reg,
46989f4f20eSPeter Maydell                                      34, "aarch64-fpu.xml", 0);
47089f4f20eSPeter Maydell         }
47189f4f20eSPeter Maydell #endif
472b355f08aSPeter Maydell     } else {
473b355f08aSPeter Maydell         if (arm_feature(env, ARM_FEATURE_NEON)) {
47489f4f20eSPeter Maydell             gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
475b355f08aSPeter Maydell                                      49, "arm-neon.xml", 0);
47689f4f20eSPeter Maydell         } else if (cpu_isar_feature(aa32_simd_r32, cpu)) {
47789f4f20eSPeter Maydell             gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
478b355f08aSPeter Maydell                                      33, "arm-vfp3.xml", 0);
47989f4f20eSPeter Maydell         } else if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
48089f4f20eSPeter Maydell             gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
481b355f08aSPeter Maydell                                      17, "arm-vfp.xml", 0);
482b355f08aSPeter Maydell         }
483b355f08aSPeter Maydell         if (!arm_feature(env, ARM_FEATURE_M)) {
484b355f08aSPeter Maydell             /*
485b355f08aSPeter Maydell              * A and R profile have FP sysregs FPEXC and FPSID that we
486b355f08aSPeter Maydell              * expose to gdb.
487b355f08aSPeter Maydell              */
488b355f08aSPeter Maydell             gdb_register_coprocessor(cs, vfp_gdb_get_sysreg, vfp_gdb_set_sysreg,
489b355f08aSPeter Maydell                                      2, "arm-vfp-sysregs.xml", 0);
490b355f08aSPeter Maydell         }
49189f4f20eSPeter Maydell     }
492*dbd9e084SPeter Maydell     if (cpu_isar_feature(aa32_mve, cpu)) {
493*dbd9e084SPeter Maydell         gdb_register_coprocessor(cs, mve_gdb_get_reg, mve_gdb_set_reg,
494*dbd9e084SPeter Maydell                                  1, "arm-m-profile-mve.xml", 0);
495*dbd9e084SPeter Maydell     }
49689f4f20eSPeter Maydell     gdb_register_coprocessor(cs, arm_gdb_get_sysreg, arm_gdb_set_sysreg,
49789f4f20eSPeter Maydell                              arm_gen_dynamic_sysreg_xml(cs, cs->gdb_num_regs),
49889f4f20eSPeter Maydell                              "system-registers.xml", 0);
49989f4f20eSPeter Maydell 
50089f4f20eSPeter Maydell }
501