xref: /openbmc/qemu/target/loongarch/gdbstub.c (revision 651ccdfa)
1 /*
2  * LOONGARCH gdb server stub
3  *
4  * Copyright (c) 2021 Loongson Technology Corporation Limited
5  *
6  * SPDX-License-Identifier: LGPL-2.1+
7  */
8 
9 #include "qemu/osdep.h"
10 #include "cpu.h"
11 #include "internals.h"
12 #include "exec/gdbstub.h"
13 #include "gdbstub/helpers.h"
14 
15 uint64_t read_fcc(CPULoongArchState *env)
16 {
17     uint64_t ret = 0;
18 
19     for (int i = 0; i < 8; ++i) {
20         ret |= (uint64_t)env->cf[i] << (i * 8);
21     }
22 
23     return ret;
24 }
25 
26 void write_fcc(CPULoongArchState *env, uint64_t val)
27 {
28     for (int i = 0; i < 8; ++i) {
29         env->cf[i] = (val >> (i * 8)) & 1;
30     }
31 }
32 
33 int loongarch_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
34 {
35     LoongArchCPU *cpu = LOONGARCH_CPU(cs);
36     CPULoongArchState *env = &cpu->env;
37 
38     if (0 <= n && n < 32) {
39         return gdb_get_regl(mem_buf, env->gpr[n]);
40     } else if (n == 32) {
41         /* orig_a0 */
42         return gdb_get_regl(mem_buf, 0);
43     } else if (n == 33) {
44         return gdb_get_regl(mem_buf, env->pc);
45     } else if (n == 34) {
46         return gdb_get_regl(mem_buf, env->CSR_BADV);
47     }
48     return 0;
49 }
50 
51 int loongarch_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
52 {
53     LoongArchCPU *cpu = LOONGARCH_CPU(cs);
54     CPULoongArchState *env = &cpu->env;
55     target_ulong tmp = ldtul_p(mem_buf);
56     int length = 0;
57 
58     if (0 <= n && n < 32) {
59         env->gpr[n] = tmp;
60         length = sizeof(target_ulong);
61     } else if (n == 33) {
62         env->pc = tmp;
63         length = sizeof(target_ulong);
64     }
65     return length;
66 }
67 
68 static int loongarch_gdb_get_fpu(CPULoongArchState *env,
69                                  GByteArray *mem_buf, int n)
70 {
71     if (0 <= n && n < 32) {
72         return gdb_get_reg64(mem_buf, env->fpr[n]);
73     } else if (n == 32) {
74         uint64_t val = read_fcc(env);
75         return gdb_get_reg64(mem_buf, val);
76     } else if (n == 33) {
77         return gdb_get_reg32(mem_buf, env->fcsr0);
78     }
79     return 0;
80 }
81 
82 static int loongarch_gdb_set_fpu(CPULoongArchState *env,
83                                  uint8_t *mem_buf, int n)
84 {
85     int length = 0;
86 
87     if (0 <= n && n < 32) {
88         env->fpr[n] = ldq_p(mem_buf);
89         length = 8;
90     } else if (n == 32) {
91         uint64_t val = ldq_p(mem_buf);
92         write_fcc(env, val);
93         length = 8;
94     } else if (n == 33) {
95         env->fcsr0 = ldl_p(mem_buf);
96         length = 4;
97     }
98     return length;
99 }
100 
101 void loongarch_cpu_register_gdb_regs_for_features(CPUState *cs)
102 {
103     gdb_register_coprocessor(cs, loongarch_gdb_get_fpu, loongarch_gdb_set_fpu,
104                              41, "loongarch-fpu.xml", 0);
105 }
106