blob: 3de3242b292dfcb3a9bc5aeb2a2374e571be1a38 [file] [log] [blame]
Andreas Färberd19c87f2013-07-07 12:29:26 +02001/*
2 * SPARC 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 */
Andreas Färber5b50e792013-06-29 04:18:45 +020020#include "config.h"
21#include "qemu-common.h"
22#include "exec/gdbstub.h"
Andreas Färberd19c87f2013-07-07 12:29:26 +020023
24#ifdef TARGET_ABI32
Andreas Färber986a2992013-07-07 13:05:05 +020025#define gdb_get_rega(buf, val) gdb_get_reg32(buf, val)
Andreas Färberd19c87f2013-07-07 12:29:26 +020026#else
Andreas Färber986a2992013-07-07 13:05:05 +020027#define gdb_get_rega(buf, val) gdb_get_regl(buf, val)
Andreas Färberd19c87f2013-07-07 12:29:26 +020028#endif
29
Andreas Färber5b50e792013-06-29 04:18:45 +020030int sparc_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
Andreas Färberd19c87f2013-07-07 12:29:26 +020031{
Andreas Färber5b50e792013-06-29 04:18:45 +020032 SPARCCPU *cpu = SPARC_CPU(cs);
33 CPUSPARCState *env = &cpu->env;
34
Andreas Färberd19c87f2013-07-07 12:29:26 +020035 if (n < 8) {
36 /* g0..g7 */
Andreas Färber986a2992013-07-07 13:05:05 +020037 return gdb_get_rega(mem_buf, env->gregs[n]);
Andreas Färberd19c87f2013-07-07 12:29:26 +020038 }
39 if (n < 32) {
40 /* register window */
Andreas Färber986a2992013-07-07 13:05:05 +020041 return gdb_get_rega(mem_buf, env->regwptr[n - 8]);
Andreas Färberd19c87f2013-07-07 12:29:26 +020042 }
43#if defined(TARGET_ABI32) || !defined(TARGET_SPARC64)
44 if (n < 64) {
45 /* fprs */
46 if (n & 1) {
Andreas Färber986a2992013-07-07 13:05:05 +020047 return gdb_get_reg32(mem_buf, env->fpr[(n - 32) / 2].l.lower);
Andreas Färberd19c87f2013-07-07 12:29:26 +020048 } else {
Andreas Färber986a2992013-07-07 13:05:05 +020049 return gdb_get_reg32(mem_buf, env->fpr[(n - 32) / 2].l.upper);
Andreas Färberd19c87f2013-07-07 12:29:26 +020050 }
51 }
52 /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
53 switch (n) {
54 case 64:
Andreas Färber986a2992013-07-07 13:05:05 +020055 return gdb_get_rega(mem_buf, env->y);
Andreas Färberd19c87f2013-07-07 12:29:26 +020056 case 65:
Andreas Färber986a2992013-07-07 13:05:05 +020057 return gdb_get_rega(mem_buf, cpu_get_psr(env));
Andreas Färberd19c87f2013-07-07 12:29:26 +020058 case 66:
Andreas Färber986a2992013-07-07 13:05:05 +020059 return gdb_get_rega(mem_buf, env->wim);
Andreas Färberd19c87f2013-07-07 12:29:26 +020060 case 67:
Andreas Färber986a2992013-07-07 13:05:05 +020061 return gdb_get_rega(mem_buf, env->tbr);
Andreas Färberd19c87f2013-07-07 12:29:26 +020062 case 68:
Andreas Färber986a2992013-07-07 13:05:05 +020063 return gdb_get_rega(mem_buf, env->pc);
Andreas Färberd19c87f2013-07-07 12:29:26 +020064 case 69:
Andreas Färber986a2992013-07-07 13:05:05 +020065 return gdb_get_rega(mem_buf, env->npc);
Andreas Färberd19c87f2013-07-07 12:29:26 +020066 case 70:
Andreas Färber986a2992013-07-07 13:05:05 +020067 return gdb_get_rega(mem_buf, env->fsr);
Andreas Färberd19c87f2013-07-07 12:29:26 +020068 case 71:
Andreas Färber986a2992013-07-07 13:05:05 +020069 return gdb_get_rega(mem_buf, 0); /* csr */
Andreas Färberd19c87f2013-07-07 12:29:26 +020070 default:
Andreas Färber986a2992013-07-07 13:05:05 +020071 return gdb_get_rega(mem_buf, 0);
Andreas Färberd19c87f2013-07-07 12:29:26 +020072 }
73#else
74 if (n < 64) {
75 /* f0-f31 */
76 if (n & 1) {
Andreas Färber986a2992013-07-07 13:05:05 +020077 return gdb_get_reg32(mem_buf, env->fpr[(n - 32) / 2].l.lower);
Andreas Färberd19c87f2013-07-07 12:29:26 +020078 } else {
Andreas Färber986a2992013-07-07 13:05:05 +020079 return gdb_get_reg32(mem_buf, env->fpr[(n - 32) / 2].l.upper);
Andreas Färberd19c87f2013-07-07 12:29:26 +020080 }
81 }
82 if (n < 80) {
83 /* f32-f62 (double width, even numbers only) */
Andreas Färber986a2992013-07-07 13:05:05 +020084 return gdb_get_reg64(mem_buf, env->fpr[(n - 32) / 2].ll);
Andreas Färberd19c87f2013-07-07 12:29:26 +020085 }
86 switch (n) {
87 case 80:
Andreas Färber986a2992013-07-07 13:05:05 +020088 return gdb_get_regl(mem_buf, env->pc);
Andreas Färberd19c87f2013-07-07 12:29:26 +020089 case 81:
Andreas Färber986a2992013-07-07 13:05:05 +020090 return gdb_get_regl(mem_buf, env->npc);
Andreas Färberd19c87f2013-07-07 12:29:26 +020091 case 82:
Andreas Färber986a2992013-07-07 13:05:05 +020092 return gdb_get_regl(mem_buf, (cpu_get_ccr(env) << 32) |
93 ((env->asi & 0xff) << 24) |
94 ((env->pstate & 0xfff) << 8) |
95 cpu_get_cwp64(env));
Andreas Färberd19c87f2013-07-07 12:29:26 +020096 case 83:
Andreas Färber986a2992013-07-07 13:05:05 +020097 return gdb_get_regl(mem_buf, env->fsr);
Andreas Färberd19c87f2013-07-07 12:29:26 +020098 case 84:
Andreas Färber986a2992013-07-07 13:05:05 +020099 return gdb_get_regl(mem_buf, env->fprs);
Andreas Färberd19c87f2013-07-07 12:29:26 +0200100 case 85:
Andreas Färber986a2992013-07-07 13:05:05 +0200101 return gdb_get_regl(mem_buf, env->y);
Andreas Färberd19c87f2013-07-07 12:29:26 +0200102 }
103#endif
104 return 0;
105}
106
Andreas Färber5b50e792013-06-29 04:18:45 +0200107int sparc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
Andreas Färberd19c87f2013-07-07 12:29:26 +0200108{
Andreas Färber5b50e792013-06-29 04:18:45 +0200109 SPARCCPU *cpu = SPARC_CPU(cs);
110 CPUSPARCState *env = &cpu->env;
Andreas Färberd19c87f2013-07-07 12:29:26 +0200111#if defined(TARGET_ABI32)
112 abi_ulong tmp;
113
114 tmp = ldl_p(mem_buf);
115#else
116 target_ulong tmp;
117
118 tmp = ldtul_p(mem_buf);
119#endif
120
121 if (n < 8) {
122 /* g0..g7 */
123 env->gregs[n] = tmp;
124 } else if (n < 32) {
125 /* register window */
126 env->regwptr[n - 8] = tmp;
127 }
128#if defined(TARGET_ABI32) || !defined(TARGET_SPARC64)
129 else if (n < 64) {
130 /* fprs */
131 /* f0-f31 */
132 if (n & 1) {
133 env->fpr[(n - 32) / 2].l.lower = tmp;
134 } else {
135 env->fpr[(n - 32) / 2].l.upper = tmp;
136 }
137 } else {
138 /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
139 switch (n) {
140 case 64:
141 env->y = tmp;
142 break;
143 case 65:
144 cpu_put_psr(env, tmp);
145 break;
146 case 66:
147 env->wim = tmp;
148 break;
149 case 67:
150 env->tbr = tmp;
151 break;
152 case 68:
153 env->pc = tmp;
154 break;
155 case 69:
156 env->npc = tmp;
157 break;
158 case 70:
159 env->fsr = tmp;
160 break;
161 default:
162 return 0;
163 }
164 }
165 return 4;
166#else
167 else if (n < 64) {
168 /* f0-f31 */
169 tmp = ldl_p(mem_buf);
170 if (n & 1) {
171 env->fpr[(n - 32) / 2].l.lower = tmp;
172 } else {
173 env->fpr[(n - 32) / 2].l.upper = tmp;
174 }
175 return 4;
176 } else if (n < 80) {
177 /* f32-f62 (double width, even numbers only) */
178 env->fpr[(n - 32) / 2].ll = tmp;
179 } else {
180 switch (n) {
181 case 80:
182 env->pc = tmp;
183 break;
184 case 81:
185 env->npc = tmp;
186 break;
187 case 82:
188 cpu_put_ccr(env, tmp >> 32);
189 env->asi = (tmp >> 24) & 0xff;
190 env->pstate = (tmp >> 8) & 0xfff;
191 cpu_put_cwp64(env, tmp & 0xff);
192 break;
193 case 83:
194 env->fsr = tmp;
195 break;
196 case 84:
197 env->fprs = tmp;
198 break;
199 case 85:
200 env->y = tmp;
201 break;
202 default:
203 return 0;
204 }
205 }
206 return 8;
207#endif
208}