xref: /openbmc/qemu/target/ppc/gdbstub.c (revision 429d3ae2)
1 /*
2  * PowerPC gdb server stub
3  *
4  * Copyright (c) 2003-2005 Fabrice Bellard
5  * Copyright (c) 2013 SUSE LINUX Products GmbH
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19  */
20 #include "qemu/osdep.h"
21 #include "qemu-common.h"
22 #include "cpu.h"
23 #include "exec/gdbstub.h"
24 
25 static int ppc_gdb_register_len_apple(int n)
26 {
27     switch (n) {
28     case 0 ... 31:
29         /* gprs */
30         return 8;
31     case 32 ... 63:
32         /* fprs */
33         return 8;
34     case 64 ... 95:
35         return 16;
36     case 64+32: /* nip */
37     case 65+32: /* msr */
38     case 67+32: /* lr */
39     case 68+32: /* ctr */
40     case 70+32: /* fpscr */
41         return 8;
42     case 66+32: /* cr */
43     case 69+32: /* xer */
44         return 4;
45     default:
46         return 0;
47     }
48 }
49 
50 static int ppc_gdb_register_len(int n)
51 {
52     switch (n) {
53     case 0 ... 31:
54         /* gprs */
55         return sizeof(target_ulong);
56     case 32 ... 63:
57         /* fprs */
58         if (gdb_has_xml) {
59             return 0;
60         }
61         return 8;
62     case 66:
63         /* cr */
64     case 69:
65         /* xer */
66         return 4;
67     case 64:
68         /* nip */
69     case 65:
70         /* msr */
71     case 67:
72         /* lr */
73     case 68:
74         /* ctr */
75         return sizeof(target_ulong);
76     case 70:
77         /* fpscr */
78         if (gdb_has_xml) {
79             return 0;
80         }
81         return sizeof(target_ulong);
82     default:
83         return 0;
84     }
85 }
86 
87 /* We need to present the registers to gdb in the "current" memory ordering.
88    For user-only mode we get this for free; TARGET_WORDS_BIGENDIAN is set to
89    the proper ordering for the binary, and cannot be changed.
90    For system mode, TARGET_WORDS_BIGENDIAN is always set, and we must check
91    the current mode of the chip to see if we're running in little-endian.  */
92 void ppc_maybe_bswap_register(CPUPPCState *env, uint8_t *mem_buf, int len)
93 {
94 #ifndef CONFIG_USER_ONLY
95     if (!msr_le) {
96         /* do nothing */
97     } else if (len == 4) {
98         bswap32s((uint32_t *)mem_buf);
99     } else if (len == 8) {
100         bswap64s((uint64_t *)mem_buf);
101     } else {
102         g_assert_not_reached();
103     }
104 #endif
105 }
106 
107 /* Old gdb always expects FP registers.  Newer (xml-aware) gdb only
108  * expects whatever the target description contains.  Due to a
109  * historical mishap the FP registers appear in between core integer
110  * regs and PC, MSR, CR, and so forth.  We hack round this by giving the
111  * FP regs zero size when talking to a newer gdb.
112  */
113 
114 int ppc_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
115 {
116     PowerPCCPU *cpu = POWERPC_CPU(cs);
117     CPUPPCState *env = &cpu->env;
118     int r = ppc_gdb_register_len(n);
119 
120     if (!r) {
121         return r;
122     }
123 
124     if (n < 32) {
125         /* gprs */
126         gdb_get_regl(mem_buf, env->gpr[n]);
127     } else if (n < 64) {
128         /* fprs */
129         stfq_p(mem_buf, env->fpr[n-32]);
130     } else {
131         switch (n) {
132         case 64:
133             gdb_get_regl(mem_buf, env->nip);
134             break;
135         case 65:
136             gdb_get_regl(mem_buf, env->msr);
137             break;
138         case 66:
139             {
140                 uint32_t cr = 0;
141                 int i;
142                 for (i = 0; i < 8; i++) {
143                     cr |= env->crf[i] << (32 - ((i + 1) * 4));
144                 }
145                 gdb_get_reg32(mem_buf, cr);
146                 break;
147             }
148         case 67:
149             gdb_get_regl(mem_buf, env->lr);
150             break;
151         case 68:
152             gdb_get_regl(mem_buf, env->ctr);
153             break;
154         case 69:
155             gdb_get_reg32(mem_buf, env->xer);
156             break;
157         case 70:
158             gdb_get_reg32(mem_buf, env->fpscr);
159             break;
160         }
161     }
162     ppc_maybe_bswap_register(env, mem_buf, r);
163     return r;
164 }
165 
166 int ppc_cpu_gdb_read_register_apple(CPUState *cs, uint8_t *mem_buf, int n)
167 {
168     PowerPCCPU *cpu = POWERPC_CPU(cs);
169     CPUPPCState *env = &cpu->env;
170     int r = ppc_gdb_register_len_apple(n);
171 
172     if (!r) {
173         return r;
174     }
175 
176     if (n < 32) {
177         /* gprs */
178         gdb_get_reg64(mem_buf, env->gpr[n]);
179     } else if (n < 64) {
180         /* fprs */
181         stfq_p(mem_buf, env->fpr[n-32]);
182     } else if (n < 96) {
183         /* Altivec */
184         stq_p(mem_buf, n - 64);
185         stq_p(mem_buf + 8, 0);
186     } else {
187         switch (n) {
188         case 64 + 32:
189             gdb_get_reg64(mem_buf, env->nip);
190             break;
191         case 65 + 32:
192             gdb_get_reg64(mem_buf, env->msr);
193             break;
194         case 66 + 32:
195             {
196                 uint32_t cr = 0;
197                 int i;
198                 for (i = 0; i < 8; i++) {
199                     cr |= env->crf[i] << (32 - ((i + 1) * 4));
200                 }
201                 gdb_get_reg32(mem_buf, cr);
202                 break;
203             }
204         case 67 + 32:
205             gdb_get_reg64(mem_buf, env->lr);
206             break;
207         case 68 + 32:
208             gdb_get_reg64(mem_buf, env->ctr);
209             break;
210         case 69 + 32:
211             gdb_get_reg32(mem_buf, env->xer);
212             break;
213         case 70 + 32:
214             gdb_get_reg64(mem_buf, env->fpscr);
215             break;
216         }
217     }
218     ppc_maybe_bswap_register(env, mem_buf, r);
219     return r;
220 }
221 
222 int ppc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
223 {
224     PowerPCCPU *cpu = POWERPC_CPU(cs);
225     CPUPPCState *env = &cpu->env;
226     int r = ppc_gdb_register_len(n);
227 
228     if (!r) {
229         return r;
230     }
231     ppc_maybe_bswap_register(env, mem_buf, r);
232     if (n < 32) {
233         /* gprs */
234         env->gpr[n] = ldtul_p(mem_buf);
235     } else if (n < 64) {
236         /* fprs */
237         env->fpr[n-32] = ldfq_p(mem_buf);
238     } else {
239         switch (n) {
240         case 64:
241             env->nip = ldtul_p(mem_buf);
242             break;
243         case 65:
244             ppc_store_msr(env, ldtul_p(mem_buf));
245             break;
246         case 66:
247             {
248                 uint32_t cr = ldl_p(mem_buf);
249                 int i;
250                 for (i = 0; i < 8; i++) {
251                     env->crf[i] = (cr >> (32 - ((i + 1) * 4))) & 0xF;
252                 }
253                 break;
254             }
255         case 67:
256             env->lr = ldtul_p(mem_buf);
257             break;
258         case 68:
259             env->ctr = ldtul_p(mem_buf);
260             break;
261         case 69:
262             env->xer = ldl_p(mem_buf);
263             break;
264         case 70:
265             /* fpscr */
266             store_fpscr(env, ldtul_p(mem_buf), 0xffffffff);
267             break;
268         }
269     }
270     return r;
271 }
272 int ppc_cpu_gdb_write_register_apple(CPUState *cs, uint8_t *mem_buf, int n)
273 {
274     PowerPCCPU *cpu = POWERPC_CPU(cs);
275     CPUPPCState *env = &cpu->env;
276     int r = ppc_gdb_register_len_apple(n);
277 
278     if (!r) {
279         return r;
280     }
281     ppc_maybe_bswap_register(env, mem_buf, r);
282     if (n < 32) {
283         /* gprs */
284         env->gpr[n] = ldq_p(mem_buf);
285     } else if (n < 64) {
286         /* fprs */
287         env->fpr[n-32] = ldfq_p(mem_buf);
288     } else {
289         switch (n) {
290         case 64 + 32:
291             env->nip = ldq_p(mem_buf);
292             break;
293         case 65 + 32:
294             ppc_store_msr(env, ldq_p(mem_buf));
295             break;
296         case 66 + 32:
297             {
298                 uint32_t cr = ldl_p(mem_buf);
299                 int i;
300                 for (i = 0; i < 8; i++) {
301                     env->crf[i] = (cr >> (32 - ((i + 1) * 4))) & 0xF;
302                 }
303                 break;
304             }
305         case 67 + 32:
306             env->lr = ldq_p(mem_buf);
307             break;
308         case 68 + 32:
309             env->ctr = ldq_p(mem_buf);
310             break;
311         case 69 + 32:
312             env->xer = ldl_p(mem_buf);
313             break;
314         case 70 + 32:
315             /* fpscr */
316             store_fpscr(env, ldq_p(mem_buf), 0xffffffff);
317             break;
318         }
319     }
320     return r;
321 }
322