xref: /openbmc/qemu/target/arm/gdbstub.c (revision 7055fe4baf4d8b331863e51a15e93d3bdea29e36)
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 
80*7055fe4bSRichard Henderson     /*
81*7055fe4bSRichard Henderson      * Mask out low bits of PC to workaround gdb bugs.
82*7055fe4bSRichard Henderson      * This avoids an assert in thumb_tr_translate_insn, because it is
83*7055fe4bSRichard Henderson      * architecturally impossible to misalign the pc.
84*7055fe4bSRichard Henderson      * This will probably cause problems if we ever implement the
85*7055fe4bSRichard Henderson      * Jazelle DBX extensions.
86*7055fe4bSRichard Henderson      */
87fcf5ef2aSThomas Huth     if (n == 15) {
88fcf5ef2aSThomas Huth         tmp &= ~1;
89fcf5ef2aSThomas Huth     }
90fcf5ef2aSThomas Huth 
91fcf5ef2aSThomas Huth     if (n < 16) {
92fcf5ef2aSThomas Huth         /* Core integer register.  */
93888f470fSPeter Maydell         if (n == 13 && arm_feature(env, ARM_FEATURE_M)) {
94888f470fSPeter Maydell             /* M profile SP low bits are always 0 */
95888f470fSPeter Maydell             tmp &= ~3;
96888f470fSPeter Maydell         }
97fcf5ef2aSThomas Huth         env->regs[n] = tmp;
98fcf5ef2aSThomas Huth         return 4;
99fcf5ef2aSThomas Huth     }
100fcf5ef2aSThomas Huth     if (n < 24) { /* 16-23 */
101fcf5ef2aSThomas Huth         /* FPA registers (ignored).  */
102fcf5ef2aSThomas Huth         if (gdb_has_xml) {
103fcf5ef2aSThomas Huth             return 0;
104fcf5ef2aSThomas Huth         }
105fcf5ef2aSThomas Huth         return 12;
106fcf5ef2aSThomas Huth     }
107fcf5ef2aSThomas Huth     switch (n) {
108fcf5ef2aSThomas Huth     case 24:
109fcf5ef2aSThomas Huth         /* FPA status register (ignored).  */
110fcf5ef2aSThomas Huth         if (gdb_has_xml) {
111fcf5ef2aSThomas Huth             return 0;
112fcf5ef2aSThomas Huth         }
113fcf5ef2aSThomas Huth         return 4;
114fcf5ef2aSThomas Huth     case 25:
115c888f7e0SPeter Maydell         /* CPSR, or XPSR for M-profile */
116c888f7e0SPeter Maydell         if (arm_feature(env, ARM_FEATURE_M)) {
117c888f7e0SPeter Maydell             /*
118c888f7e0SPeter Maydell              * Don't allow writing to XPSR.Exception as it can cause
119c888f7e0SPeter Maydell              * a transition into or out of handler mode (it's not
120c888f7e0SPeter Maydell              * writeable via the MSR insn so this is a reasonable
121c888f7e0SPeter Maydell              * restriction). Other fields are safe to update.
122c888f7e0SPeter Maydell              */
123c888f7e0SPeter Maydell             xpsr_write(env, tmp, ~XPSR_EXCP);
124c888f7e0SPeter Maydell         } else {
125fcf5ef2aSThomas Huth             cpsr_write(env, tmp, 0xffffffff, CPSRWriteByGDBStub);
126c888f7e0SPeter Maydell         }
127fcf5ef2aSThomas Huth         return 4;
128fcf5ef2aSThomas Huth     }
129fcf5ef2aSThomas Huth     /* Unknown register.  */
130fcf5ef2aSThomas Huth     return 0;
131fcf5ef2aSThomas Huth }
132200bf5b7SAbdallah Bouassida 
13389f4f20eSPeter Maydell static int vfp_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg)
13489f4f20eSPeter Maydell {
13589f4f20eSPeter Maydell     ARMCPU *cpu = env_archcpu(env);
13689f4f20eSPeter Maydell     int nregs = cpu_isar_feature(aa32_simd_r32, cpu) ? 32 : 16;
13789f4f20eSPeter Maydell 
13889f4f20eSPeter Maydell     /* VFP data registers are always little-endian.  */
13989f4f20eSPeter Maydell     if (reg < nregs) {
14089f4f20eSPeter Maydell         return gdb_get_reg64(buf, *aa32_vfp_dreg(env, reg));
14189f4f20eSPeter Maydell     }
14289f4f20eSPeter Maydell     if (arm_feature(env, ARM_FEATURE_NEON)) {
14389f4f20eSPeter Maydell         /* Aliases for Q regs.  */
14489f4f20eSPeter Maydell         nregs += 16;
14589f4f20eSPeter Maydell         if (reg < nregs) {
14689f4f20eSPeter Maydell             uint64_t *q = aa32_vfp_qreg(env, reg - 32);
14789f4f20eSPeter Maydell             return gdb_get_reg128(buf, q[0], q[1]);
14889f4f20eSPeter Maydell         }
14989f4f20eSPeter Maydell     }
15089f4f20eSPeter Maydell     switch (reg - nregs) {
15189f4f20eSPeter Maydell     case 0:
15289f4f20eSPeter Maydell         return gdb_get_reg32(buf, vfp_get_fpscr(env));
15389f4f20eSPeter Maydell     }
15489f4f20eSPeter Maydell     return 0;
15589f4f20eSPeter Maydell }
15689f4f20eSPeter Maydell 
15789f4f20eSPeter Maydell static int vfp_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
15889f4f20eSPeter Maydell {
15989f4f20eSPeter Maydell     ARMCPU *cpu = env_archcpu(env);
16089f4f20eSPeter Maydell     int nregs = cpu_isar_feature(aa32_simd_r32, cpu) ? 32 : 16;
16189f4f20eSPeter Maydell 
16289f4f20eSPeter Maydell     if (reg < nregs) {
16389f4f20eSPeter Maydell         *aa32_vfp_dreg(env, reg) = ldq_le_p(buf);
16489f4f20eSPeter Maydell         return 8;
16589f4f20eSPeter Maydell     }
16689f4f20eSPeter Maydell     if (arm_feature(env, ARM_FEATURE_NEON)) {
16789f4f20eSPeter Maydell         nregs += 16;
16889f4f20eSPeter Maydell         if (reg < nregs) {
16989f4f20eSPeter Maydell             uint64_t *q = aa32_vfp_qreg(env, reg - 32);
17089f4f20eSPeter Maydell             q[0] = ldq_le_p(buf);
17189f4f20eSPeter Maydell             q[1] = ldq_le_p(buf + 8);
17289f4f20eSPeter Maydell             return 16;
17389f4f20eSPeter Maydell         }
17489f4f20eSPeter Maydell     }
17589f4f20eSPeter Maydell     switch (reg - nregs) {
17689f4f20eSPeter Maydell     case 0:
177b355f08aSPeter Maydell         vfp_set_fpscr(env, ldl_p(buf));
178b355f08aSPeter Maydell         return 4;
179b355f08aSPeter Maydell     }
180b355f08aSPeter Maydell     return 0;
181b355f08aSPeter Maydell }
182b355f08aSPeter Maydell 
183b355f08aSPeter Maydell static int vfp_gdb_get_sysreg(CPUARMState *env, GByteArray *buf, int reg)
184b355f08aSPeter Maydell {
185b355f08aSPeter Maydell     switch (reg) {
186b355f08aSPeter Maydell     case 0:
187b355f08aSPeter Maydell         return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPSID]);
188b355f08aSPeter Maydell     case 1:
189b355f08aSPeter Maydell         return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPEXC]);
190b355f08aSPeter Maydell     }
191b355f08aSPeter Maydell     return 0;
192b355f08aSPeter Maydell }
193b355f08aSPeter Maydell 
194b355f08aSPeter Maydell static int vfp_gdb_set_sysreg(CPUARMState *env, uint8_t *buf, int reg)
195b355f08aSPeter Maydell {
196b355f08aSPeter Maydell     switch (reg) {
197b355f08aSPeter Maydell     case 0:
19889f4f20eSPeter Maydell         env->vfp.xregs[ARM_VFP_FPSID] = ldl_p(buf);
19989f4f20eSPeter Maydell         return 4;
20089f4f20eSPeter Maydell     case 1:
20189f4f20eSPeter Maydell         env->vfp.xregs[ARM_VFP_FPEXC] = ldl_p(buf) & (1 << 30);
20289f4f20eSPeter Maydell         return 4;
20389f4f20eSPeter Maydell     }
20489f4f20eSPeter Maydell     return 0;
20589f4f20eSPeter Maydell }
20689f4f20eSPeter Maydell 
207dbd9e084SPeter Maydell static int mve_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg)
208dbd9e084SPeter Maydell {
209dbd9e084SPeter Maydell     switch (reg) {
210dbd9e084SPeter Maydell     case 0:
211dbd9e084SPeter Maydell         return gdb_get_reg32(buf, env->v7m.vpr);
212dbd9e084SPeter Maydell     default:
213dbd9e084SPeter Maydell         return 0;
214dbd9e084SPeter Maydell     }
215dbd9e084SPeter Maydell }
216dbd9e084SPeter Maydell 
217dbd9e084SPeter Maydell static int mve_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
218dbd9e084SPeter Maydell {
219dbd9e084SPeter Maydell     switch (reg) {
220dbd9e084SPeter Maydell     case 0:
221dbd9e084SPeter Maydell         env->v7m.vpr = ldl_p(buf);
222dbd9e084SPeter Maydell         return 4;
223dbd9e084SPeter Maydell     default:
224dbd9e084SPeter Maydell         return 0;
225dbd9e084SPeter Maydell     }
226dbd9e084SPeter Maydell }
227dbd9e084SPeter Maydell 
22889f4f20eSPeter Maydell /**
22989f4f20eSPeter Maydell  * arm_get/set_gdb_*: get/set a gdb register
23089f4f20eSPeter Maydell  * @env: the CPU state
23189f4f20eSPeter Maydell  * @buf: a buffer to copy to/from
23289f4f20eSPeter Maydell  * @reg: register number (offset from start of group)
23389f4f20eSPeter Maydell  *
23489f4f20eSPeter Maydell  * We return the number of bytes copied
23589f4f20eSPeter Maydell  */
23689f4f20eSPeter Maydell 
23789f4f20eSPeter Maydell static int arm_gdb_get_sysreg(CPUARMState *env, GByteArray *buf, int reg)
23889f4f20eSPeter Maydell {
23989f4f20eSPeter Maydell     ARMCPU *cpu = env_archcpu(env);
24089f4f20eSPeter Maydell     const ARMCPRegInfo *ri;
24189f4f20eSPeter Maydell     uint32_t key;
24289f4f20eSPeter Maydell 
24389f4f20eSPeter Maydell     key = cpu->dyn_sysreg_xml.data.cpregs.keys[reg];
24489f4f20eSPeter Maydell     ri = get_arm_cp_reginfo(cpu->cp_regs, key);
24589f4f20eSPeter Maydell     if (ri) {
24689f4f20eSPeter Maydell         if (cpreg_field_is_64bit(ri)) {
24789f4f20eSPeter Maydell             return gdb_get_reg64(buf, (uint64_t)read_raw_cp_reg(env, ri));
24889f4f20eSPeter Maydell         } else {
24989f4f20eSPeter Maydell             return gdb_get_reg32(buf, (uint32_t)read_raw_cp_reg(env, ri));
25089f4f20eSPeter Maydell         }
25189f4f20eSPeter Maydell     }
25289f4f20eSPeter Maydell     return 0;
25389f4f20eSPeter Maydell }
25489f4f20eSPeter Maydell 
25589f4f20eSPeter Maydell static int arm_gdb_set_sysreg(CPUARMState *env, uint8_t *buf, int reg)
25689f4f20eSPeter Maydell {
25789f4f20eSPeter Maydell     return 0;
25889f4f20eSPeter Maydell }
25989f4f20eSPeter Maydell 
260448d4d14SAlex Bennée static void arm_gen_one_xml_sysreg_tag(GString *s, DynamicGDBXMLInfo *dyn_xml,
261200bf5b7SAbdallah Bouassida                                        ARMCPRegInfo *ri, uint32_t ri_key,
26232d6e32aSAlex Bennée                                        int bitsize, int regnum)
263200bf5b7SAbdallah Bouassida {
264200bf5b7SAbdallah Bouassida     g_string_append_printf(s, "<reg name=\"%s\"", ri->name);
265200bf5b7SAbdallah Bouassida     g_string_append_printf(s, " bitsize=\"%d\"", bitsize);
26632d6e32aSAlex Bennée     g_string_append_printf(s, " regnum=\"%d\"", regnum);
267200bf5b7SAbdallah Bouassida     g_string_append_printf(s, " group=\"cp_regs\"/>");
268448d4d14SAlex Bennée     dyn_xml->data.cpregs.keys[dyn_xml->num] = ri_key;
269448d4d14SAlex Bennée     dyn_xml->num++;
270200bf5b7SAbdallah Bouassida }
271200bf5b7SAbdallah Bouassida 
272200bf5b7SAbdallah Bouassida static void arm_register_sysreg_for_xml(gpointer key, gpointer value,
273200bf5b7SAbdallah Bouassida                                         gpointer p)
274200bf5b7SAbdallah Bouassida {
275200bf5b7SAbdallah Bouassida     uint32_t ri_key = *(uint32_t *)key;
276200bf5b7SAbdallah Bouassida     ARMCPRegInfo *ri = value;
277200bf5b7SAbdallah Bouassida     RegisterSysregXmlParam *param = (RegisterSysregXmlParam *)p;
278200bf5b7SAbdallah Bouassida     GString *s = param->s;
279200bf5b7SAbdallah Bouassida     ARMCPU *cpu = ARM_CPU(param->cs);
280200bf5b7SAbdallah Bouassida     CPUARMState *env = &cpu->env;
281448d4d14SAlex Bennée     DynamicGDBXMLInfo *dyn_xml = &cpu->dyn_sysreg_xml;
282200bf5b7SAbdallah Bouassida 
283200bf5b7SAbdallah Bouassida     if (!(ri->type & (ARM_CP_NO_RAW | ARM_CP_NO_GDB))) {
284200bf5b7SAbdallah Bouassida         if (arm_feature(env, ARM_FEATURE_AARCH64)) {
285200bf5b7SAbdallah Bouassida             if (ri->state == ARM_CP_STATE_AA64) {
28632d6e32aSAlex Bennée                 arm_gen_one_xml_sysreg_tag(s , dyn_xml, ri, ri_key, 64,
28732d6e32aSAlex Bennée                                            param->n++);
288200bf5b7SAbdallah Bouassida             }
289200bf5b7SAbdallah Bouassida         } else {
290200bf5b7SAbdallah Bouassida             if (ri->state == ARM_CP_STATE_AA32) {
291200bf5b7SAbdallah Bouassida                 if (!arm_feature(env, ARM_FEATURE_EL3) &&
292200bf5b7SAbdallah Bouassida                     (ri->secure & ARM_CP_SECSTATE_S)) {
293200bf5b7SAbdallah Bouassida                     return;
294200bf5b7SAbdallah Bouassida                 }
295200bf5b7SAbdallah Bouassida                 if (ri->type & ARM_CP_64BIT) {
29632d6e32aSAlex Bennée                     arm_gen_one_xml_sysreg_tag(s , dyn_xml, ri, ri_key, 64,
29732d6e32aSAlex Bennée                                                param->n++);
298200bf5b7SAbdallah Bouassida                 } else {
29932d6e32aSAlex Bennée                     arm_gen_one_xml_sysreg_tag(s , dyn_xml, ri, ri_key, 32,
30032d6e32aSAlex Bennée                                                param->n++);
301200bf5b7SAbdallah Bouassida                 }
302200bf5b7SAbdallah Bouassida             }
303200bf5b7SAbdallah Bouassida         }
304200bf5b7SAbdallah Bouassida     }
305200bf5b7SAbdallah Bouassida }
306200bf5b7SAbdallah Bouassida 
30732d6e32aSAlex Bennée int arm_gen_dynamic_sysreg_xml(CPUState *cs, int base_reg)
308200bf5b7SAbdallah Bouassida {
309200bf5b7SAbdallah Bouassida     ARMCPU *cpu = ARM_CPU(cs);
310200bf5b7SAbdallah Bouassida     GString *s = g_string_new(NULL);
31132d6e32aSAlex Bennée     RegisterSysregXmlParam param = {cs, s, base_reg};
312200bf5b7SAbdallah Bouassida 
313448d4d14SAlex Bennée     cpu->dyn_sysreg_xml.num = 0;
314448d4d14SAlex Bennée     cpu->dyn_sysreg_xml.data.cpregs.keys = g_new(uint32_t, g_hash_table_size(cpu->cp_regs));
315200bf5b7SAbdallah Bouassida     g_string_printf(s, "<?xml version=\"1.0\"?>");
316200bf5b7SAbdallah Bouassida     g_string_append_printf(s, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">");
317200bf5b7SAbdallah Bouassida     g_string_append_printf(s, "<feature name=\"org.qemu.gdb.arm.sys.regs\">");
318200bf5b7SAbdallah Bouassida     g_hash_table_foreach(cpu->cp_regs, arm_register_sysreg_for_xml, &param);
319200bf5b7SAbdallah Bouassida     g_string_append_printf(s, "</feature>");
320448d4d14SAlex Bennée     cpu->dyn_sysreg_xml.desc = g_string_free(s, false);
321448d4d14SAlex Bennée     return cpu->dyn_sysreg_xml.num;
322200bf5b7SAbdallah Bouassida }
323200bf5b7SAbdallah Bouassida 
324d12379c5SAlex Bennée struct TypeSize {
325d12379c5SAlex Bennée     const char *gdb_type;
326d12379c5SAlex Bennée     int  size;
327d12379c5SAlex Bennée     const char sz, suffix;
328d12379c5SAlex Bennée };
329d12379c5SAlex Bennée 
330d12379c5SAlex Bennée static const struct TypeSize vec_lanes[] = {
331d12379c5SAlex Bennée     /* quads */
332d12379c5SAlex Bennée     { "uint128", 128, 'q', 'u' },
333d12379c5SAlex Bennée     { "int128", 128, 'q', 's' },
334d12379c5SAlex Bennée     /* 64 bit */
335797920b9SAlex Bennée     { "ieee_double", 64, 'd', 'f' },
336d12379c5SAlex Bennée     { "uint64", 64, 'd', 'u' },
337d12379c5SAlex Bennée     { "int64", 64, 'd', 's' },
338d12379c5SAlex Bennée     /* 32 bit */
339797920b9SAlex Bennée     { "ieee_single", 32, 's', 'f' },
340d12379c5SAlex Bennée     { "uint32", 32, 's', 'u' },
341d12379c5SAlex Bennée     { "int32", 32, 's', 's' },
342d12379c5SAlex Bennée     /* 16 bit */
343797920b9SAlex Bennée     { "ieee_half", 16, 'h', 'f' },
344d12379c5SAlex Bennée     { "uint16", 16, 'h', 'u' },
345d12379c5SAlex Bennée     { "int16", 16, 'h', 's' },
346d12379c5SAlex Bennée     /* bytes */
347d12379c5SAlex Bennée     { "uint8", 8, 'b', 'u' },
348d12379c5SAlex Bennée     { "int8", 8, 'b', 's' },
349d12379c5SAlex Bennée };
350d12379c5SAlex Bennée 
351d12379c5SAlex Bennée 
352d12379c5SAlex Bennée int arm_gen_dynamic_svereg_xml(CPUState *cs, int base_reg)
353d12379c5SAlex Bennée {
354d12379c5SAlex Bennée     ARMCPU *cpu = ARM_CPU(cs);
355d12379c5SAlex Bennée     GString *s = g_string_new(NULL);
356d12379c5SAlex Bennée     DynamicGDBXMLInfo *info = &cpu->dyn_svereg_xml;
357d12379c5SAlex Bennée     g_autoptr(GString) ts = g_string_new("");
358797920b9SAlex Bennée     int i, j, bits, reg_width = (cpu->sve_max_vq * 128);
359d12379c5SAlex Bennée     info->num = 0;
360d12379c5SAlex Bennée     g_string_printf(s, "<?xml version=\"1.0\"?>");
361d12379c5SAlex Bennée     g_string_append_printf(s, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">");
362797920b9SAlex Bennée     g_string_append_printf(s, "<feature name=\"org.gnu.gdb.aarch64.sve\">");
363d12379c5SAlex Bennée 
364d12379c5SAlex Bennée     /* First define types and totals in a whole VL */
365d12379c5SAlex Bennée     for (i = 0; i < ARRAY_SIZE(vec_lanes); i++) {
366d12379c5SAlex Bennée         int count = reg_width / vec_lanes[i].size;
367797920b9SAlex Bennée         g_string_printf(ts, "svev%c%c", vec_lanes[i].sz, vec_lanes[i].suffix);
368d12379c5SAlex Bennée         g_string_append_printf(s,
369d12379c5SAlex Bennée                                "<vector id=\"%s\" type=\"%s\" count=\"%d\"/>",
370d12379c5SAlex Bennée                                ts->str, vec_lanes[i].gdb_type, count);
371d12379c5SAlex Bennée     }
372d12379c5SAlex Bennée     /*
373d12379c5SAlex Bennée      * Now define a union for each size group containing unsigned and
374d12379c5SAlex Bennée      * signed and potentially float versions of each size from 128 to
375d12379c5SAlex Bennée      * 8 bits.
376d12379c5SAlex Bennée      */
377797920b9SAlex Bennée     for (bits = 128, i = 0; bits >= 8; bits /= 2, i++) {
378797920b9SAlex Bennée         const char suf[] = { 'q', 'd', 's', 'h', 'b' };
379797920b9SAlex Bennée         g_string_append_printf(s, "<union id=\"svevn%c\">", suf[i]);
380797920b9SAlex Bennée         for (j = 0; j < ARRAY_SIZE(vec_lanes); j++) {
381797920b9SAlex Bennée             if (vec_lanes[j].size == bits) {
382797920b9SAlex Bennée                 g_string_append_printf(s, "<field name=\"%c\" type=\"svev%c%c\"/>",
383797920b9SAlex Bennée                                        vec_lanes[j].suffix,
384797920b9SAlex Bennée                                        vec_lanes[j].sz, vec_lanes[j].suffix);
385d12379c5SAlex Bennée             }
386d12379c5SAlex Bennée         }
387d12379c5SAlex Bennée         g_string_append(s, "</union>");
388d12379c5SAlex Bennée     }
389d12379c5SAlex Bennée     /* And now the final union of unions */
390797920b9SAlex Bennée     g_string_append(s, "<union id=\"svev\">");
391797920b9SAlex Bennée     for (bits = 128, i = 0; bits >= 8; bits /= 2, i++) {
392797920b9SAlex Bennée         const char suf[] = { 'q', 'd', 's', 'h', 'b' };
393797920b9SAlex Bennée         g_string_append_printf(s, "<field name=\"%c\" type=\"svevn%c\"/>",
394797920b9SAlex Bennée                                suf[i], suf[i]);
395d12379c5SAlex Bennée     }
396d12379c5SAlex Bennée     g_string_append(s, "</union>");
397d12379c5SAlex Bennée 
398797920b9SAlex Bennée     /* Finally the sve prefix type */
399797920b9SAlex Bennée     g_string_append_printf(s,
400797920b9SAlex Bennée                            "<vector id=\"svep\" type=\"uint8\" count=\"%d\"/>",
401797920b9SAlex Bennée                            reg_width / 8);
402797920b9SAlex Bennée 
403d12379c5SAlex Bennée     /* Then define each register in parts for each vq */
404d12379c5SAlex Bennée     for (i = 0; i < 32; i++) {
405d12379c5SAlex Bennée         g_string_append_printf(s,
406d12379c5SAlex Bennée                                "<reg name=\"z%d\" bitsize=\"%d\""
407797920b9SAlex Bennée                                " regnum=\"%d\" type=\"svev\"/>",
408d12379c5SAlex Bennée                                i, reg_width, base_reg++);
409d12379c5SAlex Bennée         info->num++;
410d12379c5SAlex Bennée     }
411d12379c5SAlex Bennée     /* fpscr & status registers */
412d12379c5SAlex Bennée     g_string_append_printf(s, "<reg name=\"fpsr\" bitsize=\"32\""
413d12379c5SAlex Bennée                            " regnum=\"%d\" group=\"float\""
414d12379c5SAlex Bennée                            " type=\"int\"/>", base_reg++);
415d12379c5SAlex Bennée     g_string_append_printf(s, "<reg name=\"fpcr\" bitsize=\"32\""
416d12379c5SAlex Bennée                            " regnum=\"%d\" group=\"float\""
417d12379c5SAlex Bennée                            " type=\"int\"/>", base_reg++);
418d12379c5SAlex Bennée     info->num += 2;
419797920b9SAlex Bennée 
420d12379c5SAlex Bennée     for (i = 0; i < 16; i++) {
421d12379c5SAlex Bennée         g_string_append_printf(s,
422d12379c5SAlex Bennée                                "<reg name=\"p%d\" bitsize=\"%d\""
423797920b9SAlex Bennée                                " regnum=\"%d\" type=\"svep\"/>",
424d12379c5SAlex Bennée                                i, cpu->sve_max_vq * 16, base_reg++);
425d12379c5SAlex Bennée         info->num++;
426d12379c5SAlex Bennée     }
427d12379c5SAlex Bennée     g_string_append_printf(s,
428d12379c5SAlex Bennée                            "<reg name=\"ffr\" bitsize=\"%d\""
429d12379c5SAlex Bennée                            " regnum=\"%d\" group=\"vector\""
430797920b9SAlex Bennée                            " type=\"svep\"/>",
431d12379c5SAlex Bennée                            cpu->sve_max_vq * 16, base_reg++);
432d12379c5SAlex Bennée     g_string_append_printf(s,
433d12379c5SAlex Bennée                            "<reg name=\"vg\" bitsize=\"64\""
434797920b9SAlex Bennée                            " regnum=\"%d\" type=\"int\"/>",
435d12379c5SAlex Bennée                            base_reg++);
436d12379c5SAlex Bennée     info->num += 2;
437d12379c5SAlex Bennée     g_string_append_printf(s, "</feature>");
438d12379c5SAlex Bennée     cpu->dyn_svereg_xml.desc = g_string_free(s, false);
439d12379c5SAlex Bennée 
440d12379c5SAlex Bennée     return cpu->dyn_svereg_xml.num;
441d12379c5SAlex Bennée }
442d12379c5SAlex Bennée 
443d12379c5SAlex Bennée 
444200bf5b7SAbdallah Bouassida const char *arm_gdb_get_dynamic_xml(CPUState *cs, const char *xmlname)
445200bf5b7SAbdallah Bouassida {
446200bf5b7SAbdallah Bouassida     ARMCPU *cpu = ARM_CPU(cs);
447200bf5b7SAbdallah Bouassida 
448200bf5b7SAbdallah Bouassida     if (strcmp(xmlname, "system-registers.xml") == 0) {
449448d4d14SAlex Bennée         return cpu->dyn_sysreg_xml.desc;
450d12379c5SAlex Bennée     } else if (strcmp(xmlname, "sve-registers.xml") == 0) {
451d12379c5SAlex Bennée         return cpu->dyn_svereg_xml.desc;
452200bf5b7SAbdallah Bouassida     }
453200bf5b7SAbdallah Bouassida     return NULL;
454200bf5b7SAbdallah Bouassida }
45589f4f20eSPeter Maydell 
45689f4f20eSPeter Maydell void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
45789f4f20eSPeter Maydell {
45889f4f20eSPeter Maydell     CPUState *cs = CPU(cpu);
45989f4f20eSPeter Maydell     CPUARMState *env = &cpu->env;
46089f4f20eSPeter Maydell 
46189f4f20eSPeter Maydell     if (arm_feature(env, ARM_FEATURE_AARCH64)) {
46289f4f20eSPeter Maydell         /*
46389f4f20eSPeter Maydell          * The lower part of each SVE register aliases to the FPU
46489f4f20eSPeter Maydell          * registers so we don't need to include both.
46589f4f20eSPeter Maydell          */
46689f4f20eSPeter Maydell #ifdef TARGET_AARCH64
46789f4f20eSPeter Maydell         if (isar_feature_aa64_sve(&cpu->isar)) {
46889f4f20eSPeter Maydell             gdb_register_coprocessor(cs, arm_gdb_get_svereg, arm_gdb_set_svereg,
46989f4f20eSPeter Maydell                                      arm_gen_dynamic_svereg_xml(cs, cs->gdb_num_regs),
47089f4f20eSPeter Maydell                                      "sve-registers.xml", 0);
47189f4f20eSPeter Maydell         } else {
47289f4f20eSPeter Maydell             gdb_register_coprocessor(cs, aarch64_fpu_gdb_get_reg,
47389f4f20eSPeter Maydell                                      aarch64_fpu_gdb_set_reg,
47489f4f20eSPeter Maydell                                      34, "aarch64-fpu.xml", 0);
47589f4f20eSPeter Maydell         }
47689f4f20eSPeter Maydell #endif
477b355f08aSPeter Maydell     } else {
478b355f08aSPeter Maydell         if (arm_feature(env, ARM_FEATURE_NEON)) {
47989f4f20eSPeter Maydell             gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
480b355f08aSPeter Maydell                                      49, "arm-neon.xml", 0);
48189f4f20eSPeter Maydell         } else if (cpu_isar_feature(aa32_simd_r32, cpu)) {
48289f4f20eSPeter Maydell             gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
483b355f08aSPeter Maydell                                      33, "arm-vfp3.xml", 0);
48489f4f20eSPeter Maydell         } else if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
48589f4f20eSPeter Maydell             gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
486b355f08aSPeter Maydell                                      17, "arm-vfp.xml", 0);
487b355f08aSPeter Maydell         }
488b355f08aSPeter Maydell         if (!arm_feature(env, ARM_FEATURE_M)) {
489b355f08aSPeter Maydell             /*
490b355f08aSPeter Maydell              * A and R profile have FP sysregs FPEXC and FPSID that we
491b355f08aSPeter Maydell              * expose to gdb.
492b355f08aSPeter Maydell              */
493b355f08aSPeter Maydell             gdb_register_coprocessor(cs, vfp_gdb_get_sysreg, vfp_gdb_set_sysreg,
494b355f08aSPeter Maydell                                      2, "arm-vfp-sysregs.xml", 0);
495b355f08aSPeter Maydell         }
49689f4f20eSPeter Maydell     }
497dbd9e084SPeter Maydell     if (cpu_isar_feature(aa32_mve, cpu)) {
498dbd9e084SPeter Maydell         gdb_register_coprocessor(cs, mve_gdb_get_reg, mve_gdb_set_reg,
499dbd9e084SPeter Maydell                                  1, "arm-m-profile-mve.xml", 0);
500dbd9e084SPeter Maydell     }
50189f4f20eSPeter Maydell     gdb_register_coprocessor(cs, arm_gdb_get_sysreg, arm_gdb_set_sysreg,
50289f4f20eSPeter Maydell                              arm_gen_dynamic_sysreg_xml(cs, cs->gdb_num_regs),
50389f4f20eSPeter Maydell                              "system-registers.xml", 0);
50489f4f20eSPeter Maydell 
50589f4f20eSPeter Maydell }
506