* s390-tdep.c (s390_gdbarch_init): Call set_gdbarch_get_siginfo_type.
[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
UW
128 }
129 else if (regaddr == PT_PSWADDR
130 || (regaddr >= PT_GPR0 && regaddr <= PT_GPR15))
442ea881 131 collect_register (regcache, regno, buf + sizeof (long) - size);
ee1a7ae4 132 else
442ea881 133 collect_register (regcache, regno, buf);
ee1a7ae4
UW
134
135 /* When debugging a 32-bit inferior on a 64-bit host, make sure
136 the 31-bit addressing mode bit is set in the PSW mask. */
7803799a 137 if (regaddr == PT_PSWMASK)
ee1a7ae4
UW
138 buf[size] |= 0x80;
139 }
140 else
18f5de3b 141 collect_register (regcache, regno, buf);
ee1a7ae4
UW
142}
143
144static void
493e2a69
MS
145s390_supply_ptrace_register (struct regcache *regcache,
146 int regno, const char *buf)
ee1a7ae4
UW
147{
148 int size = register_size (regno);
149 if (size < sizeof (long))
150 {
7803799a
UW
151 int regaddr = the_low_target.regmap[regno];
152
153 if ((regno ^ 1) < the_low_target.num_regs
154 && the_low_target.regmap[regno ^ 1] == regaddr)
155 {
18f5de3b
JK
156 supply_register (regcache, regno & ~1, buf);
157 supply_register (regcache, (regno & ~1) + 1,
158 buf + sizeof (long) - size);
7803799a
UW
159 }
160 else if (regaddr == PT_PSWADDR
161 || (regaddr >= PT_GPR0 && regaddr <= PT_GPR15))
442ea881 162 supply_register (regcache, regno, buf + sizeof (long) - size);
ee1a7ae4 163 else
442ea881 164 supply_register (regcache, regno, buf);
ee1a7ae4
UW
165 }
166 else
442ea881 167 supply_register (regcache, regno, buf);
ee1a7ae4
UW
168}
169
b7149293
UW
170/* Provide only a fill function for the general register set. ps_lgetregs
171 will use this for NPTL support. */
172
442ea881 173static void s390_fill_gregset (struct regcache *regcache, void *buf)
b7149293
UW
174{
175 int i;
176
7803799a
UW
177 for (i = 0; i < the_low_target.num_regs; i++)
178 {
179 if (the_low_target.regmap[i] < PT_PSWMASK
180 || the_low_target.regmap[i] > PT_ACR15)
181 continue;
182
442ea881 183 s390_collect_ptrace_register (regcache, i, (char *) buf
7803799a
UW
184 + the_low_target.regmap[i]);
185 }
b7149293
UW
186}
187
188struct regset_info target_regsets[] = {
1570b33e
L
189 { 0, 0, 0, 0, GENERAL_REGS, s390_fill_gregset, NULL },
190 { 0, 0, 0, -1, -1, NULL, NULL }
b7149293
UW
191};
192
b0ded00b 193
f450004a 194static const unsigned char s390_breakpoint[] = { 0, 1 };
b0ded00b
UW
195#define s390_breakpoint_len 2
196
197static CORE_ADDR
442ea881 198s390_get_pc (struct regcache *regcache)
b0ded00b 199{
d61ddec4
UW
200 if (register_size (0) == 4)
201 {
202 unsigned int pc;
442ea881 203 collect_register_by_name (regcache, "pswa", &pc);
b0ded00b 204#ifndef __s390x__
d61ddec4 205 pc &= 0x7fffffff;
b0ded00b 206#endif
d61ddec4
UW
207 return pc;
208 }
209 else
210 {
211 unsigned long pc;
442ea881 212 collect_register_by_name (regcache, "pswa", &pc);
d61ddec4
UW
213 return pc;
214 }
b0ded00b
UW
215}
216
217static void
442ea881 218s390_set_pc (struct regcache *regcache, CORE_ADDR newpc)
b0ded00b 219{
d61ddec4
UW
220 if (register_size (0) == 4)
221 {
222 unsigned int pc = newpc;
b0ded00b 223#ifndef __s390x__
d61ddec4 224 pc |= 0x80000000;
b0ded00b 225#endif
442ea881 226 supply_register_by_name (regcache, "pswa", &pc);
d61ddec4
UW
227 }
228 else
229 {
230 unsigned long pc = newpc;
442ea881 231 supply_register_by_name (regcache, "pswa", &pc);
d61ddec4 232 }
b0ded00b
UW
233}
234
7803799a
UW
235#ifdef __s390x__
236static unsigned long
237s390_get_hwcap (void)
238{
239 int wordsize = register_size (0);
240 unsigned char *data = alloca (2 * wordsize);
241 int offset = 0;
242
243 while ((*the_target->read_auxv) (offset, data, 2 * wordsize) == 2 * wordsize)
244 {
245 if (wordsize == 4)
246 {
247 unsigned int *data_p = (unsigned int *)data;
248 if (data_p[0] == AT_HWCAP)
249 return data_p[1];
250 }
251 else
252 {
253 unsigned long *data_p = (unsigned long *)data;
254 if (data_p[0] == AT_HWCAP)
255 return data_p[1];
256 }
257
258 offset += 2 * wordsize;
259 }
260
261 return 0;
262}
263#endif
d61ddec4
UW
264
265static void
266s390_arch_setup (void)
267{
268 /* Assume 31-bit inferior process. */
7803799a
UW
269 init_registers_s390_linux32 ();
270 the_low_target.num_regs = s390_num_regs;
271 the_low_target.regmap = s390_regmap;
d61ddec4
UW
272
273 /* On a 64-bit host, check the low bit of the (31-bit) PSWM
274 -- if this is one, we actually have a 64-bit inferior. */
275#ifdef __s390x__
276 {
277 unsigned int pswm;
92b72907
UW
278 struct regcache *regcache = new_register_cache ();
279 fetch_inferior_registers (regcache, find_regno ("pswm"));
442ea881 280 collect_register_by_name (regcache, "pswm", &pswm);
92b72907
UW
281 free_register_cache (regcache);
282
d61ddec4 283 if (pswm & 1)
7803799a
UW
284 init_registers_s390x_linux64 ();
285
286 /* For a 31-bit inferior, check whether the kernel supports
287 using the full 64-bit GPRs. */
288 else if (s390_get_hwcap () & HWCAP_S390_HIGH_GPRS)
289 {
290 init_registers_s390_linux64 ();
291 the_low_target.num_regs = s390_num_regs_3264;
292 the_low_target.regmap = s390_regmap_3264;
293 }
d61ddec4
UW
294 }
295#endif
296}
297
298
b0ded00b
UW
299static int
300s390_breakpoint_at (CORE_ADDR pc)
301{
302 unsigned char c[s390_breakpoint_len];
303 read_inferior_memory (pc, c, s390_breakpoint_len);
304 return memcmp (c, s390_breakpoint, s390_breakpoint_len) == 0;
305}
306
307
2ec06d2e 308struct linux_target_ops the_low_target = {
d61ddec4 309 s390_arch_setup,
2ec06d2e
DJ
310 s390_num_regs,
311 s390_regmap,
312 s390_cannot_fetch_register,
313 s390_cannot_store_register,
b0ded00b
UW
314 s390_get_pc,
315 s390_set_pc,
316 s390_breakpoint,
317 s390_breakpoint_len,
318 NULL,
319 s390_breakpoint_len,
320 s390_breakpoint_at,
ee1a7ae4
UW
321 NULL,
322 NULL,
323 NULL,
324 NULL,
325 s390_collect_ptrace_register,
326 s390_supply_ptrace_register,
2ec06d2e 327};
This page took 0.716162 seconds and 4 git commands to generate.