include/elf/ChangeLog:
[deliverable/binutils-gdb.git] / gdb / gdbserver / linux-s390-low.c
CommitLineData
265f716b
DJ
1/* GNU/Linux S/390 specific low level interface, for the remote server
2 for GDB.
7b6bb8da 3 Copyright (C) 2001, 2002, 2005, 2006, 2007, 2008, 2009, 2010, 2011
9b254dd1 4 Free Software Foundation, Inc.
265f716b
DJ
5
6 This file is part of GDB.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
a9762ec7 10 the Free Software Foundation; either version 3 of the License, or
265f716b
DJ
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
a9762ec7 19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
265f716b
DJ
20
21/* This file is used for both 31-bit and 64-bit S/390 systems. */
22
23#include "server.h"
24#include "linux-low.h"
25
26#include <asm/ptrace.h>
7803799a 27#include <elf.h>
265f716b 28
7803799a
UW
29#ifndef HWCAP_S390_HIGH_GPRS
30#define HWCAP_S390_HIGH_GPRS 512
31#endif
d05b4ac3 32
7803799a
UW
33/* Defined in auto-generated file s390-linux32.c. */
34void init_registers_s390_linux32 (void);
35/* Defined in auto-generated file s390-linux64.c. */
36void init_registers_s390_linux64 (void);
37/* Defined in auto-generated file s390x-linux64.c. */
38void init_registers_s390x_linux64 (void);
d05b4ac3 39
d0f54f9d 40#define s390_num_regs 51
265f716b 41
2ec06d2e 42static int s390_regmap[] = {
265f716b
DJ
43 PT_PSWMASK, PT_PSWADDR,
44
45 PT_GPR0, PT_GPR1, PT_GPR2, PT_GPR3,
46 PT_GPR4, PT_GPR5, PT_GPR6, PT_GPR7,
47 PT_GPR8, PT_GPR9, PT_GPR10, PT_GPR11,
48 PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15,
49
50 PT_ACR0, PT_ACR1, PT_ACR2, PT_ACR3,
51 PT_ACR4, PT_ACR5, PT_ACR6, PT_ACR7,
52 PT_ACR8, PT_ACR9, PT_ACR10, PT_ACR11,
53 PT_ACR12, PT_ACR13, PT_ACR14, PT_ACR15,
54
265f716b
DJ
55 PT_FPC,
56
d0f54f9d 57#ifndef __s390x__
265f716b
DJ
58 PT_FPR0_HI, PT_FPR1_HI, PT_FPR2_HI, PT_FPR3_HI,
59 PT_FPR4_HI, PT_FPR5_HI, PT_FPR6_HI, PT_FPR7_HI,
60 PT_FPR8_HI, PT_FPR9_HI, PT_FPR10_HI, PT_FPR11_HI,
61 PT_FPR12_HI, PT_FPR13_HI, PT_FPR14_HI, PT_FPR15_HI,
62#else
63 PT_FPR0, PT_FPR1, PT_FPR2, PT_FPR3,
64 PT_FPR4, PT_FPR5, PT_FPR6, PT_FPR7,
65 PT_FPR8, PT_FPR9, PT_FPR10, PT_FPR11,
66 PT_FPR12, PT_FPR13, PT_FPR14, PT_FPR15,
67#endif
68};
69
7803799a
UW
70#ifdef __s390x__
71#define s390_num_regs_3264 67
72
73static int s390_regmap_3264[] = {
74 PT_PSWMASK, PT_PSWADDR,
75
493e2a69
MS
76 PT_GPR0, PT_GPR0, PT_GPR1, PT_GPR1,
77 PT_GPR2, PT_GPR2, PT_GPR3, PT_GPR3,
78 PT_GPR4, PT_GPR4, PT_GPR5, PT_GPR5,
79 PT_GPR6, PT_GPR6, PT_GPR7, PT_GPR7,
80 PT_GPR8, PT_GPR8, PT_GPR9, PT_GPR9,
81 PT_GPR10, PT_GPR10, PT_GPR11, PT_GPR11,
82 PT_GPR12, PT_GPR12, PT_GPR13, PT_GPR13,
83 PT_GPR14, PT_GPR14, PT_GPR15, PT_GPR15,
7803799a
UW
84
85 PT_ACR0, PT_ACR1, PT_ACR2, PT_ACR3,
86 PT_ACR4, PT_ACR5, PT_ACR6, PT_ACR7,
87 PT_ACR8, PT_ACR9, PT_ACR10, PT_ACR11,
88 PT_ACR12, PT_ACR13, PT_ACR14, PT_ACR15,
89
90 PT_FPC,
91
92 PT_FPR0, PT_FPR1, PT_FPR2, PT_FPR3,
93 PT_FPR4, PT_FPR5, PT_FPR6, PT_FPR7,
94 PT_FPR8, PT_FPR9, PT_FPR10, PT_FPR11,
95 PT_FPR12, PT_FPR13, PT_FPR14, PT_FPR15,
96};
97#endif
98
99
2ec06d2e
DJ
100static int
101s390_cannot_fetch_register (int regno)
265f716b 102{
265f716b
DJ
103 return 0;
104}
105
2ec06d2e
DJ
106static int
107s390_cannot_store_register (int regno)
265f716b 108{
265f716b
DJ
109 return 0;
110}
2ec06d2e 111
ee1a7ae4 112static void
442ea881 113s390_collect_ptrace_register (struct regcache *regcache, int regno, char *buf)
ee1a7ae4
UW
114{
115 int size = register_size (regno);
116 if (size < sizeof (long))
117 {
7803799a
UW
118 int regaddr = the_low_target.regmap[regno];
119
ee1a7ae4
UW
120 memset (buf, 0, sizeof (long));
121
7803799a
UW
122 if ((regno ^ 1) < the_low_target.num_regs
123 && the_low_target.regmap[regno ^ 1] == regaddr)
124 {
18f5de3b
JK
125 collect_register (regcache, regno & ~1, buf);
126 collect_register (regcache, (regno & ~1) + 1,
127 buf + sizeof (long) - size);
7803799a 128 }
d6db1fab
UW
129 else if (regaddr == PT_PSWMASK)
130 {
131 /* Convert 4-byte PSW mask to 8 bytes by clearing bit 12 and copying
132 the basic addressing mode bit from the PSW address. */
133 char *addr = alloca (register_size (regno ^ 1));
134 collect_register (regcache, regno, buf);
135 collect_register (regcache, regno ^ 1, addr);
136 buf[1] &= ~0x8;
137 buf[size] |= (addr[0] & 0x80);
138 }
139 else if (regaddr == PT_PSWADDR)
140 {
141 /* Convert 4-byte PSW address to 8 bytes by clearing the addressing
142 mode bit (which gets copied to the PSW mask instead). */
143 collect_register (regcache, regno, buf + sizeof (long) - size);
144 buf[sizeof (long) - size] &= ~0x80;
145 }
146 else if (regaddr >= PT_GPR0 && regaddr <= PT_GPR15)
442ea881 147 collect_register (regcache, regno, buf + sizeof (long) - size);
ee1a7ae4 148 else
442ea881 149 collect_register (regcache, regno, buf);
ee1a7ae4
UW
150 }
151 else
18f5de3b 152 collect_register (regcache, regno, buf);
ee1a7ae4
UW
153}
154
155static void
493e2a69
MS
156s390_supply_ptrace_register (struct regcache *regcache,
157 int regno, const char *buf)
ee1a7ae4
UW
158{
159 int size = register_size (regno);
160 if (size < sizeof (long))
161 {
7803799a
UW
162 int regaddr = the_low_target.regmap[regno];
163
164 if ((regno ^ 1) < the_low_target.num_regs
165 && the_low_target.regmap[regno ^ 1] == regaddr)
166 {
18f5de3b
JK
167 supply_register (regcache, regno & ~1, buf);
168 supply_register (regcache, (regno & ~1) + 1,
169 buf + sizeof (long) - size);
7803799a 170 }
d6db1fab
UW
171 else if (regaddr == PT_PSWMASK)
172 {
173 /* Convert 8-byte PSW mask to 4 bytes by setting bit 12 and copying
174 the basic addressing mode into the PSW address. */
175 char *mask = alloca (size);
176 char *addr = alloca (register_size (regno ^ 1));
177 memcpy (mask, buf, size);
178 mask[1] |= 0x8;
179 supply_register (regcache, regno, mask);
180
181 collect_register (regcache, regno ^ 1, addr);
182 addr[0] &= ~0x80;
183 addr[0] |= (buf[size] & 0x80);
184 supply_register (regcache, regno ^ 1, addr);
185 }
186 else if (regaddr == PT_PSWADDR)
187 {
188 /* Convert 8-byte PSW address to 4 bytes by truncating, but
189 keeping the addressing mode bit (which was set from the mask). */
190 char *addr = alloca (size);
191 char amode;
192 collect_register (regcache, regno, addr);
193 amode = addr[0] & 0x80;
194 memcpy (addr, buf + sizeof (long) - size, size);
195 addr[0] &= ~0x80;
196 addr[0] |= amode;
197 supply_register (regcache, regno, addr);
198 }
199 else if (regaddr >= PT_GPR0 && regaddr <= PT_GPR15)
442ea881 200 supply_register (regcache, regno, buf + sizeof (long) - size);
ee1a7ae4 201 else
442ea881 202 supply_register (regcache, regno, buf);
ee1a7ae4
UW
203 }
204 else
442ea881 205 supply_register (regcache, regno, buf);
ee1a7ae4
UW
206}
207
b7149293
UW
208/* Provide only a fill function for the general register set. ps_lgetregs
209 will use this for NPTL support. */
210
442ea881 211static void s390_fill_gregset (struct regcache *regcache, void *buf)
b7149293
UW
212{
213 int i;
214
7803799a
UW
215 for (i = 0; i < the_low_target.num_regs; i++)
216 {
217 if (the_low_target.regmap[i] < PT_PSWMASK
218 || the_low_target.regmap[i] > PT_ACR15)
219 continue;
220
442ea881 221 s390_collect_ptrace_register (regcache, i, (char *) buf
7803799a
UW
222 + the_low_target.regmap[i]);
223 }
b7149293
UW
224}
225
226struct regset_info target_regsets[] = {
1570b33e
L
227 { 0, 0, 0, 0, GENERAL_REGS, s390_fill_gregset, NULL },
228 { 0, 0, 0, -1, -1, NULL, NULL }
b7149293
UW
229};
230
b0ded00b 231
f450004a 232static const unsigned char s390_breakpoint[] = { 0, 1 };
b0ded00b
UW
233#define s390_breakpoint_len 2
234
235static CORE_ADDR
442ea881 236s390_get_pc (struct regcache *regcache)
b0ded00b 237{
d61ddec4
UW
238 if (register_size (0) == 4)
239 {
d6db1fab
UW
240 unsigned int pswa;
241 collect_register_by_name (regcache, "pswa", &pswa);
242 return pswa & 0x7fffffff;
d61ddec4
UW
243 }
244 else
245 {
246 unsigned long pc;
442ea881 247 collect_register_by_name (regcache, "pswa", &pc);
d61ddec4
UW
248 return pc;
249 }
b0ded00b
UW
250}
251
252static void
442ea881 253s390_set_pc (struct regcache *regcache, CORE_ADDR newpc)
b0ded00b 254{
d61ddec4
UW
255 if (register_size (0) == 4)
256 {
d6db1fab
UW
257 unsigned int pswa;
258 collect_register_by_name (regcache, "pswa", &pswa);
259 pswa = (pswa & 0x80000000) | (newpc & 0x7fffffff);
260 supply_register_by_name (regcache, "pswa", &pswa);
d61ddec4
UW
261 }
262 else
263 {
264 unsigned long pc = newpc;
442ea881 265 supply_register_by_name (regcache, "pswa", &pc);
d61ddec4 266 }
b0ded00b
UW
267}
268
7803799a
UW
269#ifdef __s390x__
270static unsigned long
271s390_get_hwcap (void)
272{
273 int wordsize = register_size (0);
274 unsigned char *data = alloca (2 * wordsize);
275 int offset = 0;
276
277 while ((*the_target->read_auxv) (offset, data, 2 * wordsize) == 2 * wordsize)
278 {
279 if (wordsize == 4)
280 {
281 unsigned int *data_p = (unsigned int *)data;
282 if (data_p[0] == AT_HWCAP)
283 return data_p[1];
284 }
285 else
286 {
287 unsigned long *data_p = (unsigned long *)data;
288 if (data_p[0] == AT_HWCAP)
289 return data_p[1];
290 }
291
292 offset += 2 * wordsize;
293 }
294
295 return 0;
296}
297#endif
d61ddec4
UW
298
299static void
300s390_arch_setup (void)
301{
302 /* Assume 31-bit inferior process. */
7803799a
UW
303 init_registers_s390_linux32 ();
304 the_low_target.num_regs = s390_num_regs;
305 the_low_target.regmap = s390_regmap;
d61ddec4
UW
306
307 /* On a 64-bit host, check the low bit of the (31-bit) PSWM
308 -- if this is one, we actually have a 64-bit inferior. */
309#ifdef __s390x__
310 {
311 unsigned int pswm;
92b72907
UW
312 struct regcache *regcache = new_register_cache ();
313 fetch_inferior_registers (regcache, find_regno ("pswm"));
442ea881 314 collect_register_by_name (regcache, "pswm", &pswm);
92b72907
UW
315 free_register_cache (regcache);
316
d61ddec4 317 if (pswm & 1)
7803799a
UW
318 init_registers_s390x_linux64 ();
319
320 /* For a 31-bit inferior, check whether the kernel supports
321 using the full 64-bit GPRs. */
322 else if (s390_get_hwcap () & HWCAP_S390_HIGH_GPRS)
323 {
324 init_registers_s390_linux64 ();
325 the_low_target.num_regs = s390_num_regs_3264;
326 the_low_target.regmap = s390_regmap_3264;
327 }
d61ddec4
UW
328 }
329#endif
330}
331
332
b0ded00b
UW
333static int
334s390_breakpoint_at (CORE_ADDR pc)
335{
336 unsigned char c[s390_breakpoint_len];
337 read_inferior_memory (pc, c, s390_breakpoint_len);
338 return memcmp (c, s390_breakpoint, s390_breakpoint_len) == 0;
339}
340
341
2ec06d2e 342struct linux_target_ops the_low_target = {
d61ddec4 343 s390_arch_setup,
2ec06d2e
DJ
344 s390_num_regs,
345 s390_regmap,
346 s390_cannot_fetch_register,
347 s390_cannot_store_register,
b0ded00b
UW
348 s390_get_pc,
349 s390_set_pc,
350 s390_breakpoint,
351 s390_breakpoint_len,
352 NULL,
353 s390_breakpoint_len,
354 s390_breakpoint_at,
ee1a7ae4
UW
355 NULL,
356 NULL,
357 NULL,
358 NULL,
359 s390_collect_ptrace_register,
360 s390_supply_ptrace_register,
2ec06d2e 361};
This page took 0.713425 seconds and 4 git commands to generate.