Checkin gdb.arch/i386-avx.exp.
[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.
4c38e0a4 3 Copyright (C) 2001, 2002, 2005, 2006, 2007, 2008, 2009, 2010
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
76 PT_GPR0, PT_GPR0, PT_GPR1, PT_GPR1, PT_GPR2, PT_GPR2, PT_GPR3, PT_GPR3,
77 PT_GPR4, PT_GPR4, PT_GPR5, PT_GPR5, PT_GPR6, PT_GPR6, PT_GPR7, PT_GPR7,
78 PT_GPR8, PT_GPR8, PT_GPR9, PT_GPR9, PT_GPR10, PT_GPR10, PT_GPR11, PT_GPR11,
79 PT_GPR12, PT_GPR12, PT_GPR13, PT_GPR13, PT_GPR14, PT_GPR14, PT_GPR15, PT_GPR15,
80
81 PT_ACR0, PT_ACR1, PT_ACR2, PT_ACR3,
82 PT_ACR4, PT_ACR5, PT_ACR6, PT_ACR7,
83 PT_ACR8, PT_ACR9, PT_ACR10, PT_ACR11,
84 PT_ACR12, PT_ACR13, PT_ACR14, PT_ACR15,
85
86 PT_FPC,
87
88 PT_FPR0, PT_FPR1, PT_FPR2, PT_FPR3,
89 PT_FPR4, PT_FPR5, PT_FPR6, PT_FPR7,
90 PT_FPR8, PT_FPR9, PT_FPR10, PT_FPR11,
91 PT_FPR12, PT_FPR13, PT_FPR14, PT_FPR15,
92};
93#endif
94
95
2ec06d2e
DJ
96static int
97s390_cannot_fetch_register (int regno)
265f716b 98{
265f716b
DJ
99 return 0;
100}
101
2ec06d2e
DJ
102static int
103s390_cannot_store_register (int regno)
265f716b 104{
265f716b
DJ
105 return 0;
106}
2ec06d2e 107
ee1a7ae4 108static void
442ea881 109s390_collect_ptrace_register (struct regcache *regcache, int regno, char *buf)
ee1a7ae4
UW
110{
111 int size = register_size (regno);
112 if (size < sizeof (long))
113 {
7803799a
UW
114 int regaddr = the_low_target.regmap[regno];
115
ee1a7ae4
UW
116 memset (buf, 0, sizeof (long));
117
7803799a
UW
118 if ((regno ^ 1) < the_low_target.num_regs
119 && the_low_target.regmap[regno ^ 1] == regaddr)
120 {
18f5de3b
JK
121 collect_register (regcache, regno & ~1, buf);
122 collect_register (regcache, (regno & ~1) + 1,
123 buf + sizeof (long) - size);
7803799a
UW
124 }
125 else if (regaddr == PT_PSWADDR
126 || (regaddr >= PT_GPR0 && regaddr <= PT_GPR15))
442ea881 127 collect_register (regcache, regno, buf + sizeof (long) - size);
ee1a7ae4 128 else
442ea881 129 collect_register (regcache, regno, buf);
ee1a7ae4
UW
130
131 /* When debugging a 32-bit inferior on a 64-bit host, make sure
132 the 31-bit addressing mode bit is set in the PSW mask. */
7803799a 133 if (regaddr == PT_PSWMASK)
ee1a7ae4
UW
134 buf[size] |= 0x80;
135 }
136 else
18f5de3b 137 collect_register (regcache, regno, buf);
ee1a7ae4
UW
138}
139
140static void
442ea881 141s390_supply_ptrace_register (struct regcache *regcache, int regno, const char *buf)
ee1a7ae4
UW
142{
143 int size = register_size (regno);
144 if (size < sizeof (long))
145 {
7803799a
UW
146 int regaddr = the_low_target.regmap[regno];
147
148 if ((regno ^ 1) < the_low_target.num_regs
149 && the_low_target.regmap[regno ^ 1] == regaddr)
150 {
18f5de3b
JK
151 supply_register (regcache, regno & ~1, buf);
152 supply_register (regcache, (regno & ~1) + 1,
153 buf + sizeof (long) - size);
7803799a
UW
154 }
155 else if (regaddr == PT_PSWADDR
156 || (regaddr >= PT_GPR0 && regaddr <= PT_GPR15))
442ea881 157 supply_register (regcache, regno, buf + sizeof (long) - size);
ee1a7ae4 158 else
442ea881 159 supply_register (regcache, regno, buf);
ee1a7ae4
UW
160 }
161 else
442ea881 162 supply_register (regcache, regno, buf);
ee1a7ae4
UW
163}
164
b7149293
UW
165/* Provide only a fill function for the general register set. ps_lgetregs
166 will use this for NPTL support. */
167
442ea881 168static void s390_fill_gregset (struct regcache *regcache, void *buf)
b7149293
UW
169{
170 int i;
171
7803799a
UW
172 for (i = 0; i < the_low_target.num_regs; i++)
173 {
174 if (the_low_target.regmap[i] < PT_PSWMASK
175 || the_low_target.regmap[i] > PT_ACR15)
176 continue;
177
442ea881 178 s390_collect_ptrace_register (regcache, i, (char *) buf
7803799a
UW
179 + the_low_target.regmap[i]);
180 }
b7149293
UW
181}
182
183struct regset_info target_regsets[] = {
184 { 0, 0, 0, GENERAL_REGS, s390_fill_gregset, NULL },
185 { 0, 0, -1, -1, NULL, NULL }
186};
187
b0ded00b 188
f450004a 189static const unsigned char s390_breakpoint[] = { 0, 1 };
b0ded00b
UW
190#define s390_breakpoint_len 2
191
192static CORE_ADDR
442ea881 193s390_get_pc (struct regcache *regcache)
b0ded00b 194{
d61ddec4
UW
195 if (register_size (0) == 4)
196 {
197 unsigned int pc;
442ea881 198 collect_register_by_name (regcache, "pswa", &pc);
b0ded00b 199#ifndef __s390x__
d61ddec4 200 pc &= 0x7fffffff;
b0ded00b 201#endif
d61ddec4
UW
202 return pc;
203 }
204 else
205 {
206 unsigned long pc;
442ea881 207 collect_register_by_name (regcache, "pswa", &pc);
d61ddec4
UW
208 return pc;
209 }
b0ded00b
UW
210}
211
212static void
442ea881 213s390_set_pc (struct regcache *regcache, CORE_ADDR newpc)
b0ded00b 214{
d61ddec4
UW
215 if (register_size (0) == 4)
216 {
217 unsigned int pc = newpc;
b0ded00b 218#ifndef __s390x__
d61ddec4 219 pc |= 0x80000000;
b0ded00b 220#endif
442ea881 221 supply_register_by_name (regcache, "pswa", &pc);
d61ddec4
UW
222 }
223 else
224 {
225 unsigned long pc = newpc;
442ea881 226 supply_register_by_name (regcache, "pswa", &pc);
d61ddec4 227 }
b0ded00b
UW
228}
229
7803799a
UW
230#ifdef __s390x__
231static unsigned long
232s390_get_hwcap (void)
233{
234 int wordsize = register_size (0);
235 unsigned char *data = alloca (2 * wordsize);
236 int offset = 0;
237
238 while ((*the_target->read_auxv) (offset, data, 2 * wordsize) == 2 * wordsize)
239 {
240 if (wordsize == 4)
241 {
242 unsigned int *data_p = (unsigned int *)data;
243 if (data_p[0] == AT_HWCAP)
244 return data_p[1];
245 }
246 else
247 {
248 unsigned long *data_p = (unsigned long *)data;
249 if (data_p[0] == AT_HWCAP)
250 return data_p[1];
251 }
252
253 offset += 2 * wordsize;
254 }
255
256 return 0;
257}
258#endif
d61ddec4
UW
259
260static void
261s390_arch_setup (void)
262{
263 /* Assume 31-bit inferior process. */
7803799a
UW
264 init_registers_s390_linux32 ();
265 the_low_target.num_regs = s390_num_regs;
266 the_low_target.regmap = s390_regmap;
d61ddec4
UW
267
268 /* On a 64-bit host, check the low bit of the (31-bit) PSWM
269 -- if this is one, we actually have a 64-bit inferior. */
270#ifdef __s390x__
271 {
272 unsigned int pswm;
442ea881
PA
273 struct regcache *regcache = get_thread_regcache (current_inferior, 1);
274 collect_register_by_name (regcache, "pswm", &pswm);
d61ddec4 275 if (pswm & 1)
7803799a
UW
276 init_registers_s390x_linux64 ();
277
278 /* For a 31-bit inferior, check whether the kernel supports
279 using the full 64-bit GPRs. */
280 else if (s390_get_hwcap () & HWCAP_S390_HIGH_GPRS)
281 {
282 init_registers_s390_linux64 ();
283 the_low_target.num_regs = s390_num_regs_3264;
284 the_low_target.regmap = s390_regmap_3264;
285 }
d61ddec4
UW
286 }
287#endif
288}
289
290
b0ded00b
UW
291static int
292s390_breakpoint_at (CORE_ADDR pc)
293{
294 unsigned char c[s390_breakpoint_len];
295 read_inferior_memory (pc, c, s390_breakpoint_len);
296 return memcmp (c, s390_breakpoint, s390_breakpoint_len) == 0;
297}
298
299
2ec06d2e 300struct linux_target_ops the_low_target = {
d61ddec4 301 s390_arch_setup,
2ec06d2e
DJ
302 s390_num_regs,
303 s390_regmap,
304 s390_cannot_fetch_register,
305 s390_cannot_store_register,
b0ded00b
UW
306 s390_get_pc,
307 s390_set_pc,
308 s390_breakpoint,
309 s390_breakpoint_len,
310 NULL,
311 s390_breakpoint_len,
312 s390_breakpoint_at,
ee1a7ae4
UW
313 NULL,
314 NULL,
315 NULL,
316 NULL,
317 s390_collect_ptrace_register,
318 s390_supply_ptrace_register,
2ec06d2e 319};
This page took 0.574077 seconds and 4 git commands to generate.