target-i386: Loop-based copying and setting/unsetting of feature words
[qemu/ar7.git] / target-ppc / gdbstub.c
blob381a3c7e315d1dffb2ad3574385ac6b51051b1c1
1 /*
2 * PowerPC gdb server stub
4 * Copyright (c) 2003-2005 Fabrice Bellard
5 * Copyright (c) 2013 SUSE LINUX Products GmbH
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.
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.
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/>.
20 #include "config.h"
21 #include "qemu-common.h"
22 #include "exec/gdbstub.h"
24 static int ppc_gdb_register_len(int n)
26 switch (n) {
27 case 0 ... 31:
28 /* gprs */
29 return sizeof(target_ulong);
30 case 32 ... 63:
31 /* fprs */
32 if (gdb_has_xml) {
33 return 0;
35 return 8;
36 case 66:
37 /* cr */
38 return 4;
39 case 64:
40 /* nip */
41 case 65:
42 /* msr */
43 case 67:
44 /* lr */
45 case 68:
46 /* ctr */
47 case 69:
48 /* xer */
49 return sizeof(target_ulong);
50 case 70:
51 /* fpscr */
52 if (gdb_has_xml) {
53 return 0;
55 return sizeof(target_ulong);
56 default:
57 return 0;
62 static void ppc_gdb_swap_register(uint8_t *mem_buf, int n, int len)
64 if (len == 4) {
65 bswap32s((uint32_t *)mem_buf);
66 } else if (len == 8) {
67 bswap64s((uint64_t *)mem_buf);
68 } else {
69 g_assert_not_reached();
73 /* Old gdb always expects FP registers. Newer (xml-aware) gdb only
74 * expects whatever the target description contains. Due to a
75 * historical mishap the FP registers appear in between core integer
76 * regs and PC, MSR, CR, and so forth. We hack round this by giving the
77 * FP regs zero size when talking to a newer gdb.
80 int ppc_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
82 PowerPCCPU *cpu = POWERPC_CPU(cs);
83 CPUPPCState *env = &cpu->env;
84 int r = ppc_gdb_register_len(n);
86 if (!r) {
87 return r;
90 if (n < 32) {
91 /* gprs */
92 gdb_get_regl(mem_buf, env->gpr[n]);
93 } else if (n < 64) {
94 /* fprs */
95 stfq_p(mem_buf, env->fpr[n-32]);
96 } else {
97 switch (n) {
98 case 64:
99 gdb_get_regl(mem_buf, env->nip);
100 break;
101 case 65:
102 gdb_get_regl(mem_buf, env->msr);
103 break;
104 case 66:
106 uint32_t cr = 0;
107 int i;
108 for (i = 0; i < 8; i++) {
109 cr |= env->crf[i] << (32 - ((i + 1) * 4));
111 gdb_get_reg32(mem_buf, cr);
112 break;
114 case 67:
115 gdb_get_regl(mem_buf, env->lr);
116 break;
117 case 68:
118 gdb_get_regl(mem_buf, env->ctr);
119 break;
120 case 69:
121 gdb_get_regl(mem_buf, env->xer);
122 break;
123 case 70:
124 gdb_get_reg32(mem_buf, env->fpscr);
125 break;
128 if (msr_le) {
129 /* If cpu is in LE mode, convert memory contents to LE. */
130 ppc_gdb_swap_register(mem_buf, n, r);
132 return r;
135 int ppc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
137 PowerPCCPU *cpu = POWERPC_CPU(cs);
138 CPUPPCState *env = &cpu->env;
139 int r = ppc_gdb_register_len(n);
141 if (!r) {
142 return r;
144 if (msr_le) {
145 /* If cpu is in LE mode, convert memory contents to LE. */
146 ppc_gdb_swap_register(mem_buf, n, r);
148 if (n < 32) {
149 /* gprs */
150 env->gpr[n] = ldtul_p(mem_buf);
151 } else if (n < 64) {
152 /* fprs */
153 env->fpr[n-32] = ldfq_p(mem_buf);
154 } else {
155 switch (n) {
156 case 64:
157 env->nip = ldtul_p(mem_buf);
158 break;
159 case 65:
160 ppc_store_msr(env, ldtul_p(mem_buf));
161 break;
162 case 66:
164 uint32_t cr = ldl_p(mem_buf);
165 int i;
166 for (i = 0; i < 8; i++) {
167 env->crf[i] = (cr >> (32 - ((i + 1) * 4))) & 0xF;
169 break;
171 case 67:
172 env->lr = ldtul_p(mem_buf);
173 break;
174 case 68:
175 env->ctr = ldtul_p(mem_buf);
176 break;
177 case 69:
178 env->xer = ldtul_p(mem_buf);
179 break;
180 case 70:
181 /* fpscr */
182 store_fpscr(env, ldtul_p(mem_buf), 0xffffffff);
183 break;
186 return r;