]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/gdbserver/linux-s390-low.c
S390: gdbserver: Don't write guarded storage registers
[thirdparty/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.
e2882c85 3 Copyright (C) 2001-2018 Free Software Foundation, Inc.
265f716b
DJ
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
a9762ec7 9 the Free Software Foundation; either version 3 of the License, or
265f716b
DJ
10 (at your option) any later version.
11
12 This program 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
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
a9762ec7 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
265f716b
DJ
19
20/* This file is used for both 31-bit and 64-bit S/390 systems. */
21
22#include "server.h"
23#include "linux-low.h"
c642a434 24#include "elf/common.h"
f39e8743
MK
25#include "ax.h"
26#include "tracepoint.h"
265f716b
DJ
27
28#include <asm/ptrace.h>
5826e159 29#include "nat/gdb_ptrace.h"
c642a434 30#include <sys/uio.h>
7803799a 31#include <elf.h>
abd9baf9
MK
32#include <inttypes.h>
33
34#include "linux-s390-tdesc.h"
265f716b 35
7803799a
UW
36#ifndef HWCAP_S390_HIGH_GPRS
37#define HWCAP_S390_HIGH_GPRS 512
38#endif
d05b4ac3 39
6682d959
AA
40#ifndef HWCAP_S390_TE
41#define HWCAP_S390_TE 1024
42#endif
43
bf2d68ab
AA
44#ifndef HWCAP_S390_VX
45#define HWCAP_S390_VX 2048
46#endif
47
ad339634
AA
48#ifndef HWCAP_S390_GS
49#define HWCAP_S390_GS 16384
50#endif
51
c642a434 52#define s390_num_regs 52
265f716b 53
2ec06d2e 54static int s390_regmap[] = {
265f716b
DJ
55 PT_PSWMASK, PT_PSWADDR,
56
57 PT_GPR0, PT_GPR1, PT_GPR2, PT_GPR3,
58 PT_GPR4, PT_GPR5, PT_GPR6, PT_GPR7,
59 PT_GPR8, PT_GPR9, PT_GPR10, PT_GPR11,
60 PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15,
61
62 PT_ACR0, PT_ACR1, PT_ACR2, PT_ACR3,
63 PT_ACR4, PT_ACR5, PT_ACR6, PT_ACR7,
64 PT_ACR8, PT_ACR9, PT_ACR10, PT_ACR11,
65 PT_ACR12, PT_ACR13, PT_ACR14, PT_ACR15,
66
265f716b
DJ
67 PT_FPC,
68
d0f54f9d 69#ifndef __s390x__
265f716b
DJ
70 PT_FPR0_HI, PT_FPR1_HI, PT_FPR2_HI, PT_FPR3_HI,
71 PT_FPR4_HI, PT_FPR5_HI, PT_FPR6_HI, PT_FPR7_HI,
72 PT_FPR8_HI, PT_FPR9_HI, PT_FPR10_HI, PT_FPR11_HI,
73 PT_FPR12_HI, PT_FPR13_HI, PT_FPR14_HI, PT_FPR15_HI,
74#else
75 PT_FPR0, PT_FPR1, PT_FPR2, PT_FPR3,
76 PT_FPR4, PT_FPR5, PT_FPR6, PT_FPR7,
77 PT_FPR8, PT_FPR9, PT_FPR10, PT_FPR11,
78 PT_FPR12, PT_FPR13, PT_FPR14, PT_FPR15,
79#endif
c642a434
UW
80
81 PT_ORIGGPR2,
265f716b
DJ
82};
83
c642a434 84#define s390_num_regs_3264 68
7803799a 85
ab503087 86#ifdef __s390x__
7803799a
UW
87static int s390_regmap_3264[] = {
88 PT_PSWMASK, PT_PSWADDR,
89
493e2a69
MS
90 PT_GPR0, PT_GPR0, PT_GPR1, PT_GPR1,
91 PT_GPR2, PT_GPR2, PT_GPR3, PT_GPR3,
92 PT_GPR4, PT_GPR4, PT_GPR5, PT_GPR5,
93 PT_GPR6, PT_GPR6, PT_GPR7, PT_GPR7,
94 PT_GPR8, PT_GPR8, PT_GPR9, PT_GPR9,
95 PT_GPR10, PT_GPR10, PT_GPR11, PT_GPR11,
96 PT_GPR12, PT_GPR12, PT_GPR13, PT_GPR13,
97 PT_GPR14, PT_GPR14, PT_GPR15, PT_GPR15,
7803799a
UW
98
99 PT_ACR0, PT_ACR1, PT_ACR2, PT_ACR3,
100 PT_ACR4, PT_ACR5, PT_ACR6, PT_ACR7,
101 PT_ACR8, PT_ACR9, PT_ACR10, PT_ACR11,
102 PT_ACR12, PT_ACR13, PT_ACR14, PT_ACR15,
103
104 PT_FPC,
105
106 PT_FPR0, PT_FPR1, PT_FPR2, PT_FPR3,
107 PT_FPR4, PT_FPR5, PT_FPR6, PT_FPR7,
108 PT_FPR8, PT_FPR9, PT_FPR10, PT_FPR11,
109 PT_FPR12, PT_FPR13, PT_FPR14, PT_FPR15,
c642a434
UW
110
111 PT_ORIGGPR2,
7803799a 112};
ab503087
MK
113#else
114static int s390_regmap_3264[] = {
115 PT_PSWMASK, PT_PSWADDR,
116
117 -1, PT_GPR0, -1, PT_GPR1,
118 -1, PT_GPR2, -1, PT_GPR3,
119 -1, PT_GPR4, -1, PT_GPR5,
120 -1, PT_GPR6, -1, PT_GPR7,
121 -1, PT_GPR8, -1, PT_GPR9,
122 -1, PT_GPR10, -1, PT_GPR11,
123 -1, PT_GPR12, -1, PT_GPR13,
124 -1, PT_GPR14, -1, PT_GPR15,
125
126 PT_ACR0, PT_ACR1, PT_ACR2, PT_ACR3,
127 PT_ACR4, PT_ACR5, PT_ACR6, PT_ACR7,
128 PT_ACR8, PT_ACR9, PT_ACR10, PT_ACR11,
129 PT_ACR12, PT_ACR13, PT_ACR14, PT_ACR15,
130
131 PT_FPC,
132
133 PT_FPR0_HI, PT_FPR1_HI, PT_FPR2_HI, PT_FPR3_HI,
134 PT_FPR4_HI, PT_FPR5_HI, PT_FPR6_HI, PT_FPR7_HI,
135 PT_FPR8_HI, PT_FPR9_HI, PT_FPR10_HI, PT_FPR11_HI,
136 PT_FPR12_HI, PT_FPR13_HI, PT_FPR14_HI, PT_FPR15_HI,
137
138 PT_ORIGGPR2,
139};
7803799a
UW
140#endif
141
142
2ec06d2e
DJ
143static int
144s390_cannot_fetch_register (int regno)
265f716b 145{
265f716b
DJ
146 return 0;
147}
148
2ec06d2e
DJ
149static int
150s390_cannot_store_register (int regno)
265f716b 151{
265f716b
DJ
152 return 0;
153}
2ec06d2e 154
ee1a7ae4 155static void
442ea881 156s390_collect_ptrace_register (struct regcache *regcache, int regno, char *buf)
ee1a7ae4 157{
3aee8918 158 int size = register_size (regcache->tdesc, regno);
ab503087
MK
159 const struct regs_info *regs_info = (*the_low_target.regs_info) ();
160 struct usrregs_info *usr = regs_info->usrregs;
161 int regaddr = usr->regmap[regno];
162
ee1a7ae4
UW
163 if (size < sizeof (long))
164 {
165 memset (buf, 0, sizeof (long));
166
3aee8918
PA
167 if ((regno ^ 1) < usr->num_regs
168 && usr->regmap[regno ^ 1] == regaddr)
7803799a 169 {
18f5de3b
JK
170 collect_register (regcache, regno & ~1, buf);
171 collect_register (regcache, (regno & ~1) + 1,
172 buf + sizeof (long) - size);
7803799a 173 }
d6db1fab
UW
174 else if (regaddr == PT_PSWMASK)
175 {
176 /* Convert 4-byte PSW mask to 8 bytes by clearing bit 12 and copying
177 the basic addressing mode bit from the PSW address. */
3451269c 178 gdb_byte *addr = (gdb_byte *) alloca (register_size (regcache->tdesc, regno ^ 1));
d6db1fab
UW
179 collect_register (regcache, regno, buf);
180 collect_register (regcache, regno ^ 1, addr);
181 buf[1] &= ~0x8;
182 buf[size] |= (addr[0] & 0x80);
183 }
184 else if (regaddr == PT_PSWADDR)
185 {
186 /* Convert 4-byte PSW address to 8 bytes by clearing the addressing
187 mode bit (which gets copied to the PSW mask instead). */
188 collect_register (regcache, regno, buf + sizeof (long) - size);
189 buf[sizeof (long) - size] &= ~0x80;
190 }
c642a434
UW
191 else if ((regaddr >= PT_GPR0 && regaddr <= PT_GPR15)
192 || regaddr == PT_ORIGGPR2)
442ea881 193 collect_register (regcache, regno, buf + sizeof (long) - size);
ee1a7ae4 194 else
442ea881 195 collect_register (regcache, regno, buf);
ee1a7ae4 196 }
ab503087 197 else if (regaddr != -1)
18f5de3b 198 collect_register (regcache, regno, buf);
ee1a7ae4
UW
199}
200
201static void
493e2a69
MS
202s390_supply_ptrace_register (struct regcache *regcache,
203 int regno, const char *buf)
ee1a7ae4 204{
3aee8918 205 int size = register_size (regcache->tdesc, regno);
ab503087
MK
206 const struct regs_info *regs_info = (*the_low_target.regs_info) ();
207 struct usrregs_info *usr = regs_info->usrregs;
208 int regaddr = usr->regmap[regno];
209
ee1a7ae4
UW
210 if (size < sizeof (long))
211 {
3aee8918
PA
212 if ((regno ^ 1) < usr->num_regs
213 && usr->regmap[regno ^ 1] == regaddr)
7803799a 214 {
18f5de3b
JK
215 supply_register (regcache, regno & ~1, buf);
216 supply_register (regcache, (regno & ~1) + 1,
217 buf + sizeof (long) - size);
7803799a 218 }
d6db1fab
UW
219 else if (regaddr == PT_PSWMASK)
220 {
221 /* Convert 8-byte PSW mask to 4 bytes by setting bit 12 and copying
222 the basic addressing mode into the PSW address. */
3451269c
PA
223 gdb_byte *mask = (gdb_byte *) alloca (size);
224 gdb_byte *addr = (gdb_byte *) alloca (register_size (regcache->tdesc, regno ^ 1));
d6db1fab
UW
225 memcpy (mask, buf, size);
226 mask[1] |= 0x8;
227 supply_register (regcache, regno, mask);
228
229 collect_register (regcache, regno ^ 1, addr);
230 addr[0] &= ~0x80;
231 addr[0] |= (buf[size] & 0x80);
232 supply_register (regcache, regno ^ 1, addr);
233 }
234 else if (regaddr == PT_PSWADDR)
235 {
236 /* Convert 8-byte PSW address to 4 bytes by truncating, but
237 keeping the addressing mode bit (which was set from the mask). */
3451269c 238 gdb_byte *addr = (gdb_byte *) alloca (size);
d6db1fab
UW
239 char amode;
240 collect_register (regcache, regno, addr);
241 amode = addr[0] & 0x80;
242 memcpy (addr, buf + sizeof (long) - size, size);
243 addr[0] &= ~0x80;
244 addr[0] |= amode;
245 supply_register (regcache, regno, addr);
246 }
c642a434
UW
247 else if ((regaddr >= PT_GPR0 && regaddr <= PT_GPR15)
248 || regaddr == PT_ORIGGPR2)
442ea881 249 supply_register (regcache, regno, buf + sizeof (long) - size);
ee1a7ae4 250 else
442ea881 251 supply_register (regcache, regno, buf);
ee1a7ae4 252 }
ab503087 253 else if (regaddr != -1)
442ea881 254 supply_register (regcache, regno, buf);
ee1a7ae4
UW
255}
256
b7149293
UW
257/* Provide only a fill function for the general register set. ps_lgetregs
258 will use this for NPTL support. */
259
3aee8918
PA
260static void
261s390_fill_gregset (struct regcache *regcache, void *buf)
b7149293
UW
262{
263 int i;
3aee8918
PA
264 const struct regs_info *regs_info = (*the_low_target.regs_info) ();
265 struct usrregs_info *usr = regs_info->usrregs;
b7149293 266
3aee8918 267 for (i = 0; i < usr->num_regs; i++)
7803799a 268 {
3aee8918
PA
269 if (usr->regmap[i] < PT_PSWMASK
270 || usr->regmap[i] > PT_ACR15)
7803799a
UW
271 continue;
272
3aee8918
PA
273 s390_collect_ptrace_register (regcache, i,
274 (char *) buf + usr->regmap[i]);
7803799a 275 }
b7149293
UW
276}
277
c642a434
UW
278/* Fill and store functions for extended register sets. */
279
ab503087
MK
280#ifndef __s390x__
281static void
282s390_fill_gprs_high (struct regcache *regcache, void *buf)
283{
284 int r0h = find_regno (regcache->tdesc, "r0h");
285 int i;
286
287 for (i = 0; i < 16; i++)
288 collect_register (regcache, r0h + 2 * i, (char *) buf + 4 * i);
289}
290
291static void
292s390_store_gprs_high (struct regcache *regcache, const void *buf)
293{
294 int r0h = find_regno (regcache->tdesc, "r0h");
295 int i;
296
297 for (i = 0; i < 16; i++)
298 supply_register (regcache, r0h + 2 * i, (const char *) buf + 4 * i);
299}
300#endif
301
c642a434
UW
302static void
303s390_store_last_break (struct regcache *regcache, const void *buf)
304{
3aee8918
PA
305 const char *p;
306
307 p = (const char *) buf + 8 - register_size (regcache->tdesc, 0);
308 supply_register_by_name (regcache, "last_break", p);
c642a434
UW
309}
310
311static void
312s390_fill_system_call (struct regcache *regcache, void *buf)
313{
314 collect_register_by_name (regcache, "system_call", buf);
315}
316
317static void
318s390_store_system_call (struct regcache *regcache, const void *buf)
319{
320 supply_register_by_name (regcache, "system_call", buf);
321}
322
e5a9158d
AA
323static void
324s390_store_tdb (struct regcache *regcache, const void *buf)
325{
326 int tdb0 = find_regno (regcache->tdesc, "tdb0");
327 int tr0 = find_regno (regcache->tdesc, "tr0");
328 int i;
329
330 for (i = 0; i < 4; i++)
331 supply_register (regcache, tdb0 + i, (const char *) buf + 8 * i);
332
333 for (i = 0; i < 16; i++)
334 supply_register (regcache, tr0 + i, (const char *) buf + 8 * (16 + i));
335}
336
bf2d68ab
AA
337static void
338s390_fill_vxrs_low (struct regcache *regcache, void *buf)
339{
340 int v0 = find_regno (regcache->tdesc, "v0l");
341 int i;
342
343 for (i = 0; i < 16; i++)
344 collect_register (regcache, v0 + i, (char *) buf + 8 * i);
345}
346
347static void
348s390_store_vxrs_low (struct regcache *regcache, const void *buf)
349{
350 int v0 = find_regno (regcache->tdesc, "v0l");
351 int i;
352
353 for (i = 0; i < 16; i++)
354 supply_register (regcache, v0 + i, (const char *) buf + 8 * i);
355}
356
357static void
358s390_fill_vxrs_high (struct regcache *regcache, void *buf)
359{
360 int v16 = find_regno (regcache->tdesc, "v16");
361 int i;
362
363 for (i = 0; i < 16; i++)
364 collect_register (regcache, v16 + i, (char *) buf + 16 * i);
365}
366
367static void
368s390_store_vxrs_high (struct regcache *regcache, const void *buf)
369{
370 int v16 = find_regno (regcache->tdesc, "v16");
371 int i;
372
373 for (i = 0; i < 16; i++)
374 supply_register (regcache, v16 + i, (const char *) buf + 16 * i);
375}
376
ad339634
AA
377static void
378s390_store_gs (struct regcache *regcache, const void *buf)
379{
380 int gsd = find_regno (regcache->tdesc, "gsd");
381 int i;
382
383 for (i = 0; i < 3; i++)
384 supply_register (regcache, gsd + i, (const char *) buf + 8 * (i + 1));
385}
386
ad339634
AA
387static void
388s390_store_gsbc (struct regcache *regcache, const void *buf)
389{
390 int bc_gsd = find_regno (regcache->tdesc, "bc_gsd");
391 int i;
392
393 for (i = 0; i < 3; i++)
394 supply_register (regcache, bc_gsd + i, (const char *) buf + 8 * (i + 1));
395}
396
3aee8918 397static struct regset_info s390_regsets[] = {
1570b33e 398 { 0, 0, 0, 0, GENERAL_REGS, s390_fill_gregset, NULL },
ab503087
MK
399#ifndef __s390x__
400 { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_S390_HIGH_GPRS, 0,
401 EXTENDED_REGS, s390_fill_gprs_high, s390_store_gprs_high },
402#endif
feea5f36
AA
403 /* Last break address is read-only; no fill function. */
404 { PTRACE_GETREGSET, -1, NT_S390_LAST_BREAK, 0, EXTENDED_REGS,
405 NULL, s390_store_last_break },
c642a434
UW
406 { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_S390_SYSTEM_CALL, 0,
407 EXTENDED_REGS, s390_fill_system_call, s390_store_system_call },
e5a9158d
AA
408 /* TDB is read-only. */
409 { PTRACE_GETREGSET, -1, NT_S390_TDB, 0, EXTENDED_REGS,
410 NULL, s390_store_tdb },
bf2d68ab
AA
411 { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_S390_VXRS_LOW, 0,
412 EXTENDED_REGS, s390_fill_vxrs_low, s390_store_vxrs_low },
413 { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_S390_VXRS_HIGH, 0,
414 EXTENDED_REGS, s390_fill_vxrs_high, s390_store_vxrs_high },
c49bd90b
AA
415 /* Guarded storage registers are read-only. */
416 { PTRACE_GETREGSET, -1, NT_S390_GS_CB, 0, EXTENDED_REGS,
417 NULL, s390_store_gs },
418 { PTRACE_GETREGSET, -1, NT_S390_GS_BC, 0, EXTENDED_REGS,
419 NULL, s390_store_gsbc },
50bc912a 420 NULL_REGSET
b7149293
UW
421};
422
b0ded00b 423
dd373349 424static const gdb_byte s390_breakpoint[] = { 0, 1 };
b0ded00b
UW
425#define s390_breakpoint_len 2
426
dd373349
AT
427/* Implementation of linux_target_ops method "sw_breakpoint_from_kind". */
428
429static const gdb_byte *
430s390_sw_breakpoint_from_kind (int kind, int *size)
431{
432 *size = s390_breakpoint_len;
433 return s390_breakpoint;
434}
435
b0ded00b 436static CORE_ADDR
442ea881 437s390_get_pc (struct regcache *regcache)
b0ded00b 438{
3aee8918 439 if (register_size (regcache->tdesc, 0) == 4)
d61ddec4 440 {
d6db1fab
UW
441 unsigned int pswa;
442 collect_register_by_name (regcache, "pswa", &pswa);
443 return pswa & 0x7fffffff;
d61ddec4
UW
444 }
445 else
446 {
447 unsigned long pc;
442ea881 448 collect_register_by_name (regcache, "pswa", &pc);
d61ddec4
UW
449 return pc;
450 }
b0ded00b
UW
451}
452
453static void
442ea881 454s390_set_pc (struct regcache *regcache, CORE_ADDR newpc)
b0ded00b 455{
3aee8918 456 if (register_size (regcache->tdesc, 0) == 4)
d61ddec4 457 {
d6db1fab
UW
458 unsigned int pswa;
459 collect_register_by_name (regcache, "pswa", &pswa);
460 pswa = (pswa & 0x80000000) | (newpc & 0x7fffffff);
461 supply_register_by_name (regcache, "pswa", &pswa);
d61ddec4
UW
462 }
463 else
464 {
465 unsigned long pc = newpc;
442ea881 466 supply_register_by_name (regcache, "pswa", &pc);
d61ddec4 467 }
b0ded00b
UW
468}
469
7edb9bd3
AA
470/* Get HWCAP from AUXV, using the given WORDSIZE. Return the HWCAP, or
471 zero if not found. */
472
7803799a 473static unsigned long
7edb9bd3 474s390_get_hwcap (int wordsize)
7803799a 475{
3451269c 476 gdb_byte *data = (gdb_byte *) alloca (2 * wordsize);
7803799a
UW
477 int offset = 0;
478
479 while ((*the_target->read_auxv) (offset, data, 2 * wordsize) == 2 * wordsize)
480 {
481 if (wordsize == 4)
482 {
483 unsigned int *data_p = (unsigned int *)data;
484 if (data_p[0] == AT_HWCAP)
485 return data_p[1];
486 }
487 else
488 {
489 unsigned long *data_p = (unsigned long *)data;
490 if (data_p[0] == AT_HWCAP)
491 return data_p[1];
492 }
493
494 offset += 2 * wordsize;
495 }
496
497 return 0;
498}
d61ddec4 499
7edb9bd3
AA
500/* Determine the word size for the given PID, in bytes. */
501
502#ifdef __s390x__
503static int
504s390_get_wordsize (int pid)
505{
506 errno = 0;
507 PTRACE_XFER_TYPE pswm = ptrace (PTRACE_PEEKUSER, pid,
508 (PTRACE_TYPE_ARG3) 0,
509 (PTRACE_TYPE_ARG4) 0);
510 if (errno != 0) {
511 warning (_("Couldn't determine word size, assuming 64-bit.\n"));
512 return 8;
513 }
514 /* Derive word size from extended addressing mode (PSW bit 31). */
515 return pswm & (1L << 32) ? 8 : 4;
516}
517#else
518#define s390_get_wordsize(pid) 4
519#endif
520
c642a434
UW
521static int
522s390_check_regset (int pid, int regset, int regsize)
523{
3451269c 524 void *buf = alloca (regsize);
c642a434
UW
525 struct iovec iov;
526
527 iov.iov_base = buf;
528 iov.iov_len = regsize;
529
4ac33720
UW
530 if (ptrace (PTRACE_GETREGSET, pid, (long) regset, (long) &iov) >= 0
531 || errno == ENODATA)
c642a434 532 return 1;
4ac33720 533 return 0;
c642a434
UW
534}
535
3aee8918
PA
536/* For a 31-bit inferior, whether the kernel supports using the full
537 64-bit GPRs. */
538static int have_hwcap_s390_high_gprs = 0;
abd9baf9 539static int have_hwcap_s390_vx = 0;
3aee8918 540
d61ddec4
UW
541static void
542s390_arch_setup (void)
543{
3aee8918 544 const struct target_desc *tdesc;
c642a434
UW
545 struct regset_info *regset;
546
7edb9bd3 547 /* Determine word size and HWCAP. */
0bfdf32f 548 int pid = pid_of (current_thread);
7edb9bd3
AA
549 int wordsize = s390_get_wordsize (pid);
550 unsigned long hwcap = s390_get_hwcap (wordsize);
551
552 /* Check whether the kernel supports extra register sets. */
c642a434
UW
553 int have_regset_last_break
554 = s390_check_regset (pid, NT_S390_LAST_BREAK, 8);
555 int have_regset_system_call
556 = s390_check_regset (pid, NT_S390_SYSTEM_CALL, 4);
7edb9bd3
AA
557 int have_regset_tdb
558 = (s390_check_regset (pid, NT_S390_TDB, 256)
559 && (hwcap & HWCAP_S390_TE) != 0);
560 int have_regset_vxrs
561 = (s390_check_regset (pid, NT_S390_VXRS_LOW, 128)
562 && s390_check_regset (pid, NT_S390_VXRS_HIGH, 256)
563 && (hwcap & HWCAP_S390_VX) != 0);
564 int have_regset_gs
565 = (s390_check_regset (pid, NT_S390_GS_CB, 32)
566 && s390_check_regset (pid, NT_S390_GS_BC, 32)
567 && (hwcap & HWCAP_S390_GS) != 0);
d61ddec4 568
d61ddec4 569 {
ab503087 570#ifdef __s390x__
7edb9bd3 571 if (wordsize == 8)
c642a434 572 {
ad339634
AA
573 if (have_regset_gs)
574 tdesc = tdesc_s390x_gs_linux64;
575 else if (have_regset_vxrs)
bf2d68ab
AA
576 tdesc = (have_regset_tdb ? tdesc_s390x_tevx_linux64 :
577 tdesc_s390x_vx_linux64);
578 else if (have_regset_tdb)
4ac33720 579 tdesc = tdesc_s390x_te_linux64;
6682d959 580 else if (have_regset_system_call)
3aee8918 581 tdesc = tdesc_s390x_linux64v2;
c642a434 582 else if (have_regset_last_break)
3aee8918 583 tdesc = tdesc_s390x_linux64v1;
c642a434 584 else
3aee8918 585 tdesc = tdesc_s390x_linux64;
c642a434 586 }
7803799a
UW
587
588 /* For a 31-bit inferior, check whether the kernel supports
589 using the full 64-bit GPRs. */
ab503087
MK
590 else
591#endif
7edb9bd3 592 if (hwcap & HWCAP_S390_HIGH_GPRS)
7803799a 593 {
3aee8918 594 have_hwcap_s390_high_gprs = 1;
ad339634
AA
595 if (have_regset_gs)
596 tdesc = tdesc_s390_gs_linux64;
597 else if (have_regset_vxrs)
bf2d68ab
AA
598 tdesc = (have_regset_tdb ? tdesc_s390_tevx_linux64 :
599 tdesc_s390_vx_linux64);
600 else if (have_regset_tdb)
4ac33720
UW
601 tdesc = tdesc_s390_te_linux64;
602 else if (have_regset_system_call)
3aee8918 603 tdesc = tdesc_s390_linux64v2;
c642a434 604 else if (have_regset_last_break)
3aee8918 605 tdesc = tdesc_s390_linux64v1;
c642a434 606 else
3aee8918 607 tdesc = tdesc_s390_linux64;
7803799a 608 }
7edb9bd3
AA
609 else
610 {
611 /* Assume 31-bit inferior process. */
612 if (have_regset_system_call)
613 tdesc = tdesc_s390_linux32v2;
614 else if (have_regset_last_break)
615 tdesc = tdesc_s390_linux32v1;
616 else
617 tdesc = tdesc_s390_linux32;
618 }
abd9baf9
MK
619
620 have_hwcap_s390_vx = have_regset_vxrs;
d61ddec4 621 }
6682d959
AA
622
623 /* Update target_regsets according to available register sets. */
feea5f36 624 for (regset = s390_regsets; regset->size >= 0; regset++)
6682d959
AA
625 if (regset->get_request == PTRACE_GETREGSET)
626 switch (regset->nt_type)
627 {
ab503087
MK
628#ifndef __s390x__
629 case NT_S390_HIGH_GPRS:
630 regset->size = have_hwcap_s390_high_gprs ? 64 : 0;
631 break;
632#endif
6682d959 633 case NT_S390_LAST_BREAK:
ab503087 634 regset->size = have_regset_last_break ? 8 : 0;
6682d959
AA
635 break;
636 case NT_S390_SYSTEM_CALL:
ab503087 637 regset->size = have_regset_system_call ? 4 : 0;
6682d959
AA
638 break;
639 case NT_S390_TDB:
640 regset->size = have_regset_tdb ? 256 : 0;
bf2d68ab
AA
641 break;
642 case NT_S390_VXRS_LOW:
643 regset->size = have_regset_vxrs ? 128 : 0;
644 break;
645 case NT_S390_VXRS_HIGH:
646 regset->size = have_regset_vxrs ? 256 : 0;
647 break;
ad339634
AA
648 case NT_S390_GS_CB:
649 case NT_S390_GS_BC:
650 regset->size = have_regset_gs ? 32 : 0;
6682d959
AA
651 default:
652 break;
653 }
654
3aee8918 655 current_process ()->tdesc = tdesc;
d61ddec4
UW
656}
657
658
b0ded00b
UW
659static int
660s390_breakpoint_at (CORE_ADDR pc)
661{
662 unsigned char c[s390_breakpoint_len];
663 read_inferior_memory (pc, c, s390_breakpoint_len);
664 return memcmp (c, s390_breakpoint, s390_breakpoint_len) == 0;
665}
666
b00b61e1
MK
667/* Breakpoint/Watchpoint support. */
668
669/* The "supports_z_point_type" linux_target_ops method. */
670
671static int
672s390_supports_z_point_type (char z_type)
673{
674 switch (z_type)
675 {
676 case Z_PACKET_SW_BP:
677 return 1;
678 default:
679 return 0;
680 }
681}
682
7d00775e
AT
683/* Support for hardware single step. */
684
685static int
686s390_supports_hardware_single_step (void)
687{
688 return 1;
689}
690
3aee8918
PA
691static struct usrregs_info s390_usrregs_info =
692 {
693 s390_num_regs,
694 s390_regmap,
695 };
696
697static struct regsets_info s390_regsets_info =
698 {
699 s390_regsets, /* regsets */
700 0, /* num_regsets */
701 NULL, /* disabled_regsets */
702 };
703
704static struct regs_info regs_info =
705 {
706 NULL, /* regset_bitmap */
707 &s390_usrregs_info,
708 &s390_regsets_info
709 };
710
3aee8918
PA
711static struct usrregs_info s390_usrregs_info_3264 =
712 {
713 s390_num_regs_3264,
714 s390_regmap_3264
715 };
716
717static struct regsets_info s390_regsets_info_3264 =
718 {
719 s390_regsets, /* regsets */
720 0, /* num_regsets */
721 NULL, /* disabled_regsets */
722 };
723
724static struct regs_info regs_info_3264 =
725 {
726 NULL, /* regset_bitmap */
727 &s390_usrregs_info_3264,
728 &s390_regsets_info_3264
729 };
3aee8918
PA
730
731static const struct regs_info *
732s390_regs_info (void)
733{
3aee8918
PA
734 if (have_hwcap_s390_high_gprs)
735 {
ab503087 736#ifdef __s390x__
3aee8918
PA
737 const struct target_desc *tdesc = current_process ()->tdesc;
738
739 if (register_size (tdesc, 0) == 4)
740 return &regs_info_3264;
ab503087
MK
741#else
742 return &regs_info_3264;
3aee8918 743#endif
ab503087 744 }
3aee8918
PA
745 return &regs_info;
746}
b0ded00b 747
a4105d04
MK
748/* The "supports_tracepoints" linux_target_ops method. */
749
750static int
751s390_supports_tracepoints (void)
752{
753 return 1;
754}
755
abd9baf9
MK
756/* Implementation of linux_target_ops method "get_thread_area". */
757
758static int
759s390_get_thread_area (int lwpid, CORE_ADDR *addrp)
760{
761 CORE_ADDR res = ptrace (PTRACE_PEEKUSER, lwpid, (long) PT_ACR0, (long) 0);
762#ifdef __s390x__
763 struct regcache *regcache = get_thread_regcache (current_thread, 0);
764
765 if (register_size (regcache->tdesc, 0) == 4)
766 res &= 0xffffffffull;
767#endif
768 *addrp = res;
769 return 0;
770}
771
772
773/* Fast tracepoint support.
774
775 The register save area on stack is identical for all targets:
776
777 0x000+i*0x10: VR0-VR31
778 0x200+i*8: GR0-GR15
779 0x280+i*4: AR0-AR15
780 0x2c0: PSWM [64-bit]
781 0x2c8: PSWA [64-bit]
782 0x2d0: FPC
783
784 If we're on 31-bit linux, we just don't store the high parts of the GPRs.
785 Likewise, if there's no VX support, we just store the FRs into the slots
786 of low VR halves. The agent code is responsible for rearranging that
787 into regcache. */
788
789/* Code sequence saving GPRs for 31-bit target with no high GPRs. There's
790 one trick used at the very beginning: since there's no way to allocate
791 stack space without destroying CC (lay instruction can do it, but it's
792 only supported on later CPUs), we take 4 different execution paths for
793 every possible value of CC, allocate stack space, save %r0, stuff the
794 CC value in %r0 (shifted to match its position in PSWM high word),
795 then branch to common path. */
796
797static const unsigned char s390_ft_entry_gpr_esa[] = {
798 0xa7, 0x14, 0x00, 0x1e, /* jo .Lcc3 */
799 0xa7, 0x24, 0x00, 0x14, /* jh .Lcc2 */
800 0xa7, 0x44, 0x00, 0x0a, /* jl .Lcc1 */
801 /* CC = 0 */
802 0xa7, 0xfa, 0xfd, 0x00, /* ahi %r15, -0x300 */
803 0x50, 0x00, 0xf2, 0x04, /* st %r0, 0x204(%r15) */
804 0xa7, 0x08, 0x00, 0x00, /* lhi %r0, 0 */
805 0xa7, 0xf4, 0x00, 0x18, /* j .Lccdone */
806 /* .Lcc1: */
807 0xa7, 0xfa, 0xfd, 0x00, /* ahi %r15, -0x300 */
808 0x50, 0x00, 0xf2, 0x04, /* st %r0, 0x204(%r15) */
809 0xa7, 0x08, 0x10, 0x00, /* lhi %r0, 0x1000 */
810 0xa7, 0xf4, 0x00, 0x10, /* j .Lccdone */
811 /* .Lcc2: */
812 0xa7, 0xfa, 0xfd, 0x00, /* ahi %r15, -0x300 */
813 0x50, 0x00, 0xf2, 0x04, /* st %r0, 0x204(%r15) */
814 0xa7, 0x08, 0x20, 0x00, /* lhi %r0, 0x2000 */
815 0xa7, 0xf4, 0x00, 0x08, /* j .Lccdone */
816 /* .Lcc3: */
817 0xa7, 0xfa, 0xfd, 0x00, /* ahi %r15, -0x300 */
818 0x50, 0x00, 0xf2, 0x04, /* st %r0, 0x204(%r15) */
819 0xa7, 0x08, 0x30, 0x00, /* lhi %r0, 0x3000 */
820 /* .Lccdone: */
821 0x50, 0x10, 0xf2, 0x0c, /* st %r1, 0x20c(%r15) */
822 0x50, 0x20, 0xf2, 0x14, /* st %r2, 0x214(%r15) */
823 0x50, 0x30, 0xf2, 0x1c, /* st %r3, 0x21c(%r15) */
824 0x50, 0x40, 0xf2, 0x24, /* st %r4, 0x224(%r15) */
825 0x50, 0x50, 0xf2, 0x2c, /* st %r5, 0x22c(%r15) */
826 0x50, 0x60, 0xf2, 0x34, /* st %r6, 0x234(%r15) */
827 0x50, 0x70, 0xf2, 0x3c, /* st %r7, 0x23c(%r15) */
828 0x50, 0x80, 0xf2, 0x44, /* st %r8, 0x244(%r15) */
829 0x50, 0x90, 0xf2, 0x4c, /* st %r9, 0x24c(%r15) */
830 0x50, 0xa0, 0xf2, 0x54, /* st %r10, 0x254(%r15) */
831 0x50, 0xb0, 0xf2, 0x5c, /* st %r11, 0x25c(%r15) */
832 0x50, 0xc0, 0xf2, 0x64, /* st %r12, 0x264(%r15) */
833 0x50, 0xd0, 0xf2, 0x6c, /* st %r13, 0x26c(%r15) */
834 0x50, 0xe0, 0xf2, 0x74, /* st %r14, 0x274(%r15) */
835 /* Compute original value of %r15 and store it. We use ahi instead
836 of la to preserve the whole value, and not just the low 31 bits.
837 This is not particularly important here, but essential in the
838 zarch case where someone might be using the high word of %r15
839 as an extra register. */
840 0x18, 0x1f, /* lr %r1, %r15 */
841 0xa7, 0x1a, 0x03, 0x00, /* ahi %r1, 0x300 */
842 0x50, 0x10, 0xf2, 0x7c, /* st %r1, 0x27c(%r15) */
843};
844
845/* Code sequence saving GPRs for 31-bit target with high GPRs and for 64-bit
846 target. Same as above, except this time we can use load/store multiple,
847 since the 64-bit regs are tightly packed. */
848
849static const unsigned char s390_ft_entry_gpr_zarch[] = {
850 0xa7, 0x14, 0x00, 0x21, /* jo .Lcc3 */
851 0xa7, 0x24, 0x00, 0x16, /* jh .Lcc2 */
852 0xa7, 0x44, 0x00, 0x0b, /* jl .Lcc1 */
853 /* CC = 0 */
854 0xa7, 0xfb, 0xfd, 0x00, /* aghi %r15, -0x300 */
855 0xeb, 0x0e, 0xf2, 0x00, 0x00, 0x24, /* stmg %r0, %r14, 0x200(%r15) */
856 0xa7, 0x08, 0x00, 0x00, /* lhi %r0, 0 */
857 0xa7, 0xf4, 0x00, 0x1b, /* j .Lccdone */
858 /* .Lcc1: */
859 0xa7, 0xfb, 0xfd, 0x00, /* aghi %r15, -0x300 */
860 0xeb, 0x0e, 0xf2, 0x00, 0x00, 0x24, /* stmg %r0, %r14, 0x200(%r15) */
861 0xa7, 0x08, 0x10, 0x00, /* lhi %r0, 0x1000 */
862 0xa7, 0xf4, 0x00, 0x12, /* j .Lccdone */
863 /* .Lcc2: */
864 0xa7, 0xfb, 0xfd, 0x00, /* aghi %r15, -0x300 */
865 0xeb, 0x0e, 0xf2, 0x00, 0x00, 0x24, /* stmg %r0, %r14, 0x200(%r15) */
866 0xa7, 0x08, 0x20, 0x00, /* lhi %r0, 0x2000 */
867 0xa7, 0xf4, 0x00, 0x09, /* j .Lccdone */
868 /* .Lcc3: */
869 0xa7, 0xfb, 0xfd, 0x00, /* aghi %r15, -0x300 */
870 0xeb, 0x0e, 0xf2, 0x00, 0x00, 0x24, /* stmg %r0, %r14, 0x200(%r15) */
871 0xa7, 0x08, 0x30, 0x00, /* lhi %r0, 0x3000 */
872 /* .Lccdone: */
873 0xb9, 0x04, 0x00, 0x1f, /* lgr %r1, %r15 */
874 0xa7, 0x1b, 0x03, 0x00, /* aghi %r1, 0x300 */
875 0xe3, 0x10, 0xf2, 0x78, 0x00, 0x24, /* stg %r1, 0x278(%r15) */
876};
877
878/* Code sequence saving ARs, PSWM and FPC. PSWM has to be assembled from
879 current PSWM (read by epsw) and CC from entry (in %r0). */
880
881static const unsigned char s390_ft_entry_misc[] = {
882 0x9b, 0x0f, 0xf2, 0x80, /* stam %a0, %a15, 0x20(%%r15) */
883 0xb9, 0x8d, 0x00, 0x23, /* epsw %r2, %r3 */
884 0xa7, 0x18, 0xcf, 0xff, /* lhi %r1, ~0x3000 */
885 0x14, 0x21, /* nr %r2, %r1 */
886 0x16, 0x20, /* or %r2, %r0 */
887 0x50, 0x20, 0xf2, 0xc0, /* st %r2, 0x2c0(%r15) */
888 0x50, 0x30, 0xf2, 0xc4, /* st %r3, 0x2c4(%r15) */
889 0xb2, 0x9c, 0xf2, 0xd0, /* stfpc 0x2d0(%r15) */
890};
891
892/* Code sequence saving FRs, used if VX not supported. */
893
894static const unsigned char s390_ft_entry_fr[] = {
895 0x60, 0x00, 0xf0, 0x00, /* std %f0, 0x000(%r15) */
896 0x60, 0x10, 0xf0, 0x10, /* std %f1, 0x010(%r15) */
897 0x60, 0x20, 0xf0, 0x20, /* std %f2, 0x020(%r15) */
898 0x60, 0x30, 0xf0, 0x30, /* std %f3, 0x030(%r15) */
899 0x60, 0x40, 0xf0, 0x40, /* std %f4, 0x040(%r15) */
900 0x60, 0x50, 0xf0, 0x50, /* std %f5, 0x050(%r15) */
901 0x60, 0x60, 0xf0, 0x60, /* std %f6, 0x060(%r15) */
902 0x60, 0x70, 0xf0, 0x70, /* std %f7, 0x070(%r15) */
903 0x60, 0x80, 0xf0, 0x80, /* std %f8, 0x080(%r15) */
904 0x60, 0x90, 0xf0, 0x90, /* std %f9, 0x090(%r15) */
905 0x60, 0xa0, 0xf0, 0xa0, /* std %f10, 0x0a0(%r15) */
906 0x60, 0xb0, 0xf0, 0xb0, /* std %f11, 0x0b0(%r15) */
907 0x60, 0xc0, 0xf0, 0xc0, /* std %f12, 0x0c0(%r15) */
908 0x60, 0xd0, 0xf0, 0xd0, /* std %f13, 0x0d0(%r15) */
909 0x60, 0xe0, 0xf0, 0xe0, /* std %f14, 0x0e0(%r15) */
910 0x60, 0xf0, 0xf0, 0xf0, /* std %f15, 0x0f0(%r15) */
911};
912
913/* Code sequence saving VRs, used if VX not supported. */
914
915static const unsigned char s390_ft_entry_vr[] = {
916 0xe7, 0x0f, 0xf0, 0x00, 0x00, 0x3e, /* vstm %v0, %v15, 0x000(%r15) */
917 0xe7, 0x0f, 0xf1, 0x00, 0x0c, 0x3e, /* vstm %v16, %v31, 0x100(%r15) */
918};
919
920/* Code sequence doing the collection call for 31-bit target. %r1 contains
921 the address of the literal pool. */
922
923static const unsigned char s390_ft_main_31[] = {
924 /* Load the literals into registers. */
925 0x58, 0x50, 0x10, 0x00, /* l %r5, 0x0(%r1) */
926 0x58, 0x20, 0x10, 0x04, /* l %r2, 0x4(%r1) */
927 0x58, 0x40, 0x10, 0x08, /* l %r4, 0x8(%r1) */
928 0x58, 0x60, 0x10, 0x0c, /* l %r6, 0xc(%r1) */
929 /* Save original PSWA (tracepoint address | 0x80000000). */
930 0x50, 0x50, 0xf2, 0xcc, /* st %r5, 0x2cc(%r15) */
931 /* Construct a collecting_t object at %r15+0x2e0. */
932 0x50, 0x20, 0xf2, 0xe0, /* st %r2, 0x2e0(%r15) */
933 0x9b, 0x00, 0xf2, 0xe4, /* stam %a0, %a0, 0x2e4(%r15) */
934 /* Move its address to %r0. */
935 0x41, 0x00, 0xf2, 0xe0, /* la %r0, 0x2e0(%r15) */
936 /* Take the lock. */
937 /* .Lloop: */
938 0xa7, 0x18, 0x00, 0x00, /* lhi %r1, 0 */
939 0xba, 0x10, 0x60, 0x00, /* cs %r1, %r0, 0(%r6) */
940 0xa7, 0x74, 0xff, 0xfc, /* jne .Lloop */
941 /* Address of the register save block to %r3. */
942 0x18, 0x3f, /* lr %r3, %r15 */
943 /* Make a stack frame, so that we can call the collector. */
944 0xa7, 0xfa, 0xff, 0xa0, /* ahi %r15, -0x60 */
945 /* Call it. */
946 0x0d, 0xe4, /* basr %r14, %r4 */
947 /* And get rid of the stack frame again. */
948 0x41, 0xf0, 0xf0, 0x60, /* la %r15, 0x60(%r15) */
949 /* Leave the lock. */
950 0x07, 0xf0, /* br %r0 */
951 0xa7, 0x18, 0x00, 0x00, /* lhi %r1, 0 */
952 0x50, 0x10, 0x60, 0x00, /* st %t1, 0(%r6) */
953};
954
955/* Code sequence doing the collection call for 64-bit target. %r1 contains
956 the address of the literal pool. */
957
958static const unsigned char s390_ft_main_64[] = {
959 /* Load the literals into registers. */
960 0xe3, 0x50, 0x10, 0x00, 0x00, 0x04, /* lg %r5, 0x00(%r1) */
961 0xe3, 0x20, 0x10, 0x08, 0x00, 0x04, /* lg %r2, 0x08(%r1) */
962 0xe3, 0x40, 0x10, 0x10, 0x00, 0x04, /* lg %r4, 0x10(%r1) */
963 0xe3, 0x60, 0x10, 0x18, 0x00, 0x04, /* lg %r6, 0x18(%r1) */
964 /* Save original PSWA (tracepoint address). */
965 0xe3, 0x50, 0xf2, 0xc8, 0x00, 0x24, /* stg %r5, 0x2c8(%r15) */
966 /* Construct a collecting_t object at %r15+0x2e0. */
967 0xe3, 0x20, 0xf2, 0xe0, 0x00, 0x24, /* stg %r2, 0x2e0(%r15) */
968 0x9b, 0x01, 0xf2, 0xe8, /* stam %a0, %a1, 0x2e8(%r15) */
969 /* Move its address to %r0. */
970 0x41, 0x00, 0xf2, 0xe0, /* la %r0, 0x2e0(%r15) */
971 /* Take the lock. */
972 /* .Lloop: */
973 0xa7, 0x19, 0x00, 0x00, /* lghi %r1, 0 */
974 0xeb, 0x10, 0x60, 0x00, 0x00, 0x30, /* csg %r1, %r0, 0(%r6) */
975 0xa7, 0x74, 0xff, 0xfb, /* jne .Lloop */
976 /* Address of the register save block to %r3. */
977 0xb9, 0x04, 0x00, 0x3f, /* lgr %r3, %r15 */
978 /* Make a stack frame, so that we can call the collector. */
979 0xa7, 0xfb, 0xff, 0x60, /* aghi %r15, -0xa0 */
980 /* Call it. */
981 0x0d, 0xe4, /* basr %r14, %r4 */
982 /* And get rid of the stack frame again. */
983 0x41, 0xf0, 0xf0, 0xa0, /* la %r15, 0xa0(%r15) */
984 /* Leave the lock. */
985 0x07, 0xf0, /* br %r0 */
986 0xa7, 0x19, 0x00, 0x00, /* lghi %r1, 0 */
987 0xe3, 0x10, 0x60, 0x00, 0x00, 0x24, /* stg %t1, 0(%r6) */
988};
989
990/* Code sequence restoring FRs, for targets with no VX support. */
991
992static const unsigned char s390_ft_exit_fr[] = {
993 0x68, 0x00, 0xf0, 0x00, /* ld %f0, 0x000(%r15) */
994 0x68, 0x10, 0xf0, 0x10, /* ld %f1, 0x010(%r15) */
995 0x68, 0x20, 0xf0, 0x20, /* ld %f2, 0x020(%r15) */
996 0x68, 0x30, 0xf0, 0x30, /* ld %f3, 0x030(%r15) */
997 0x68, 0x40, 0xf0, 0x40, /* ld %f4, 0x040(%r15) */
998 0x68, 0x50, 0xf0, 0x50, /* ld %f5, 0x050(%r15) */
999 0x68, 0x60, 0xf0, 0x60, /* ld %f6, 0x060(%r15) */
1000 0x68, 0x70, 0xf0, 0x70, /* ld %f7, 0x070(%r15) */
1001 0x68, 0x80, 0xf0, 0x80, /* ld %f8, 0x080(%r15) */
1002 0x68, 0x90, 0xf0, 0x90, /* ld %f9, 0x090(%r15) */
1003 0x68, 0xa0, 0xf0, 0xa0, /* ld %f10, 0x0a0(%r15) */
1004 0x68, 0xb0, 0xf0, 0xb0, /* ld %f11, 0x0b0(%r15) */
1005 0x68, 0xc0, 0xf0, 0xc0, /* ld %f12, 0x0c0(%r15) */
1006 0x68, 0xd0, 0xf0, 0xd0, /* ld %f13, 0x0d0(%r15) */
1007 0x68, 0xe0, 0xf0, 0xe0, /* ld %f14, 0x0e0(%r15) */
1008 0x68, 0xf0, 0xf0, 0xf0, /* ld %f15, 0x0f0(%r15) */
1009};
1010
1011/* Code sequence restoring VRs. */
1012
1013static const unsigned char s390_ft_exit_vr[] = {
1014 0xe7, 0x0f, 0xf0, 0x00, 0x00, 0x36, /* vlm %v0, %v15, 0x000(%r15) */
1015 0xe7, 0x0f, 0xf1, 0x00, 0x0c, 0x36, /* vlm %v16, %v31, 0x100(%r15) */
1016};
1017
1018/* Code sequence restoring misc registers. As for PSWM, only CC should be
1019 modified by C code, so we use the alr instruction to restore it by
1020 manufacturing an operand that'll result in the original flags. */
1021
1022static const unsigned char s390_ft_exit_misc[] = {
1023 0xb2, 0x9d, 0xf2, 0xd0, /* lfpc 0x2d0(%r15) */
1024 0x58, 0x00, 0xf2, 0xc0, /* l %r0, 0x2c0(%r15) */
1025 /* Extract CC to high 2 bits of %r0. */
1026 0x88, 0x00, 0x00, 0x0c, /* srl %r0, 12 */
1027 0x89, 0x00, 0x00, 0x1e, /* sll %r0, 30 */
1028 /* Add %r0 to itself. Result will be nonzero iff CC bit 0 is set, and
1029 will have carry iff CC bit 1 is set - resulting in the same flags
1030 as the original. */
1031 0x1e, 0x00, /* alr %r0, %r0 */
1032 0x9a, 0x0f, 0xf2, 0x80, /* lam %a0, %a15, 0x280(%r15) */
1033};
1034
1035/* Code sequence restoring GPRs, for 31-bit targets with no high GPRs. */
1036
1037static const unsigned char s390_ft_exit_gpr_esa[] = {
1038 0x58, 0x00, 0xf2, 0x04, /* l %r0, 0x204(%r15) */
1039 0x58, 0x10, 0xf2, 0x0c, /* l %r1, 0x20c(%r15) */
1040 0x58, 0x20, 0xf2, 0x14, /* l %r2, 0x214(%r15) */
1041 0x58, 0x30, 0xf2, 0x1c, /* l %r3, 0x21c(%r15) */
1042 0x58, 0x40, 0xf2, 0x24, /* l %r4, 0x224(%r15) */
1043 0x58, 0x50, 0xf2, 0x2c, /* l %r5, 0x22c(%r15) */
1044 0x58, 0x60, 0xf2, 0x34, /* l %r6, 0x234(%r15) */
1045 0x58, 0x70, 0xf2, 0x3c, /* l %r7, 0x23c(%r15) */
1046 0x58, 0x80, 0xf2, 0x44, /* l %r8, 0x244(%r15) */
1047 0x58, 0x90, 0xf2, 0x4c, /* l %r9, 0x24c(%r15) */
1048 0x58, 0xa0, 0xf2, 0x54, /* l %r10, 0x254(%r15) */
1049 0x58, 0xb0, 0xf2, 0x5c, /* l %r11, 0x25c(%r15) */
1050 0x58, 0xc0, 0xf2, 0x64, /* l %r12, 0x264(%r15) */
1051 0x58, 0xd0, 0xf2, 0x6c, /* l %r13, 0x26c(%r15) */
1052 0x58, 0xe0, 0xf2, 0x74, /* l %r14, 0x274(%r15) */
1053 0x58, 0xf0, 0xf2, 0x7c, /* l %r15, 0x27c(%r15) */
1054};
1055
1056/* Code sequence restoring GPRs, for 64-bit targets and 31-bit targets
1057 with high GPRs. */
1058
1059static const unsigned char s390_ft_exit_gpr_zarch[] = {
1060 0xeb, 0x0f, 0xf2, 0x00, 0x00, 0x04, /* lmg %r0, %r15, 0x200(%r15) */
1061};
1062
1063/* Writes instructions to target, updating the to pointer. */
1064
1065static void
1066append_insns (CORE_ADDR *to, size_t len, const unsigned char *buf)
1067{
1068 write_inferior_memory (*to, buf, len);
1069 *to += len;
1070}
1071
1072/* Relocates an instruction from oldloc to *to, updating to. */
1073
1074static int
1075s390_relocate_instruction (CORE_ADDR *to, CORE_ADDR oldloc, int is_64)
1076{
1077 gdb_byte buf[6];
1078 int ilen;
1079 int op2;
1080 /* 0: no fixup, 1: PC16DBL fixup, 2: PC32DBL fixup. */
1081 int mode = 0;
1082 int is_bras = 0;
1083 read_inferior_memory (oldloc, buf, sizeof buf);
1084 if (buf[0] < 0x40)
1085 ilen = 2;
1086 else if (buf[0] < 0xc0)
1087 ilen = 4;
1088 else
1089 ilen = 6;
1090 switch (buf[0])
1091 {
1092 case 0x05: /* BALR */
1093 case 0x0c: /* BASSM */
1094 case 0x0d: /* BASR */
1095 case 0x45: /* BAL */
1096 case 0x4d: /* BAS */
1097 /* These save a return address and mess around with registers.
1098 We can't relocate them. */
1099 return 1;
1100 case 0x84: /* BRXH */
1101 case 0x85: /* BRXLE */
1102 mode = 1;
1103 break;
1104 case 0xa7:
1105 op2 = buf[1] & 0xf;
1106 /* BRC, BRAS, BRCT, BRCTG */
1107 if (op2 >= 4 && op2 <= 7)
1108 mode = 1;
1109 /* BRAS */
1110 if (op2 == 5)
1111 is_bras = 1;
1112 break;
1113 case 0xc0:
1114 op2 = buf[1] & 0xf;
1115 /* LARL, BRCL, BRASL */
1116 if (op2 == 0 || op2 == 4 || op2 == 5)
1117 mode = 2;
1118 /* BRASL */
1119 if (op2 == 5)
1120 is_bras = 1;
1121 break;
1122 case 0xc4:
1123 case 0xc6:
1124 /* PC-relative addressing instructions. */
1125 mode = 2;
1126 break;
1127 case 0xc5: /* BPRP */
1128 case 0xc7: /* BPP */
1129 /* Branch prediction - just skip it. */
1130 return 0;
1131 case 0xcc:
1132 op2 = buf[1] & 0xf;
1133 /* BRCTH */
1134 if (op2 == 6)
1135 mode = 2;
1136 break;
1137 case 0xec:
1138 op2 = buf[5];
1139 switch (op2)
1140 {
1141 case 0x44: /* BRXHG */
1142 case 0x45: /* BRXLG */
1143 case 0x64: /* CGRJ */
1144 case 0x65: /* CLGRJ */
1145 case 0x76: /* CRJ */
1146 case 0x77: /* CLRJ */
1147 mode = 1;
1148 break;
1149 }
1150 break;
1151 }
1152
1153 if (mode != 0)
1154 {
1155 /* We'll have to relocate an instruction with a PC-relative field.
1156 First, compute the target. */
1157 int64_t loffset = 0;
1158 CORE_ADDR target;
1159 if (mode == 1)
1160 {
1161 int16_t soffset = 0;
1162 memcpy (&soffset, buf + 2, 2);
1163 loffset = soffset;
1164 }
1165 else if (mode == 2)
1166 {
1167 int32_t soffset = 0;
1168 memcpy (&soffset, buf + 2, 4);
1169 loffset = soffset;
1170 }
1171 target = oldloc + loffset * 2;
1172 if (!is_64)
1173 target &= 0x7fffffff;
1174
1175 if (is_bras)
1176 {
1177 /* BRAS or BRASL was used. We cannot just relocate those, since
1178 they save the return address in a register. We can, however,
1179 replace them with a LARL+JG sequence. */
1180
1181 /* Make the LARL. */
1182 int32_t soffset;
1183 buf[0] = 0xc0;
1184 buf[1] &= 0xf0;
1185 loffset = oldloc + ilen - *to;
1186 loffset >>= 1;
1187 soffset = loffset;
1188 if (soffset != loffset && is_64)
1189 return 1;
1190 memcpy (buf + 2, &soffset, 4);
1191 append_insns (to, 6, buf);
1192
1193 /* Note: this is not fully correct. In 31-bit mode, LARL will write
1194 an address with the top bit 0, while BRAS/BRASL will write it
1195 with top bit 1. It should not matter much, since linux compilers
1196 use BR and not BSM to return from functions, but it could confuse
1197 some poor stack unwinder. */
1198
1199 /* We'll now be writing a JG. */
1200 mode = 2;
1201 buf[0] = 0xc0;
1202 buf[1] = 0xf4;
1203 ilen = 6;
1204 }
1205
1206 /* Compute the new offset and write it to the buffer. */
1207 loffset = target - *to;
1208 loffset >>= 1;
1209
1210 if (mode == 1)
1211 {
1212 int16_t soffset = loffset;
1213 if (soffset != loffset)
1214 return 1;
1215 memcpy (buf + 2, &soffset, 2);
1216 }
1217 else if (mode == 2)
1218 {
1219 int32_t soffset = loffset;
1220 if (soffset != loffset && is_64)
1221 return 1;
1222 memcpy (buf + 2, &soffset, 4);
1223 }
1224 }
1225 append_insns (to, ilen, buf);
1226 return 0;
1227}
1228
1229/* Implementation of linux_target_ops method
1230 "install_fast_tracepoint_jump_pad". */
1231
1232static int
1233s390_install_fast_tracepoint_jump_pad (CORE_ADDR tpoint,
1234 CORE_ADDR tpaddr,
1235 CORE_ADDR collector,
1236 CORE_ADDR lockaddr,
1237 ULONGEST orig_size,
1238 CORE_ADDR *jump_entry,
1239 CORE_ADDR *trampoline,
1240 ULONGEST *trampoline_size,
1241 unsigned char *jjump_pad_insn,
1242 ULONGEST *jjump_pad_insn_size,
1243 CORE_ADDR *adjusted_insn_addr,
1244 CORE_ADDR *adjusted_insn_addr_end,
1245 char *err)
1246{
1247 int i;
1248 int64_t loffset;
1249 int32_t offset;
1250 unsigned char jbuf[6] = { 0xc0, 0xf4, 0, 0, 0, 0 }; /* jg ... */
1251 CORE_ADDR buildaddr = *jump_entry;
1252#ifdef __s390x__
1253 struct regcache *regcache = get_thread_regcache (current_thread, 0);
1254 int is_64 = register_size (regcache->tdesc, 0) == 8;
1255 int is_zarch = is_64 || have_hwcap_s390_high_gprs;
1256 int has_vx = have_hwcap_s390_vx;
1257#else
1258 int is_64 = 0, is_zarch = 0, has_vx = 0;
1259#endif
1260 CORE_ADDR literals[4] = {
1261 tpaddr,
1262 tpoint,
1263 collector,
1264 lockaddr,
1265 };
1266
1267 /* First, store the GPRs. */
1268 if (is_zarch)
1269 append_insns (&buildaddr, sizeof s390_ft_entry_gpr_zarch,
1270 s390_ft_entry_gpr_zarch);
1271 else
1272 append_insns (&buildaddr, sizeof s390_ft_entry_gpr_esa,
1273 s390_ft_entry_gpr_esa);
1274
1275 /* Second, misc registers (ARs, PSWM, FPC). PSWA will be stored below. */
1276 append_insns (&buildaddr, sizeof s390_ft_entry_misc, s390_ft_entry_misc);
1277
1278 /* Third, FRs or VRs. */
1279 if (has_vx)
1280 append_insns (&buildaddr, sizeof s390_ft_entry_vr, s390_ft_entry_vr);
1281 else
1282 append_insns (&buildaddr, sizeof s390_ft_entry_fr, s390_ft_entry_fr);
1283
1284 /* Now, the main part of code - store PSWA, take lock, call collector,
1285 leave lock. First, we'll need to fetch 4 literals. */
1286 if (is_64) {
1287 unsigned char buf[] = {
1288 0x07, 0x07, /* nopr %r7 */
1289 0x07, 0x07, /* nopr %r7 */
1290 0x07, 0x07, /* nopr %r7 */
1291 0xa7, 0x15, 0x00, 0x12, /* bras %r1, .Lend */
1292 0, 0, 0, 0, 0, 0, 0, 0, /* tpaddr */
1293 0, 0, 0, 0, 0, 0, 0, 0, /* tpoint */
1294 0, 0, 0, 0, 0, 0, 0, 0, /* collector */
1295 0, 0, 0, 0, 0, 0, 0, 0, /* lockaddr */
1296 /* .Lend: */
1297 };
1298 /* Find the proper start place in buf, so that literals will be
1299 aligned. */
1300 int bufpos = (buildaddr + 2) & 7;
1301 /* Stuff the literals into the buffer. */
1302 for (i = 0; i < 4; i++) {
1303 uint64_t lit = literals[i];
1304 memcpy (&buf[sizeof buf - 32 + i * 8], &lit, 8);
1305 }
1306 append_insns (&buildaddr, sizeof buf - bufpos, buf + bufpos);
1307 append_insns (&buildaddr, sizeof s390_ft_main_64, s390_ft_main_64);
1308 } else {
1309 unsigned char buf[] = {
1310 0x07, 0x07, /* nopr %r7 */
1311 0xa7, 0x15, 0x00, 0x0a, /* bras %r1, .Lend */
1312 0, 0, 0, 0, /* tpaddr */
1313 0, 0, 0, 0, /* tpoint */
1314 0, 0, 0, 0, /* collector */
1315 0, 0, 0, 0, /* lockaddr */
1316 /* .Lend: */
1317 };
1318 /* Find the proper start place in buf, so that literals will be
1319 aligned. */
1320 int bufpos = (buildaddr + 2) & 3;
1321 /* First literal will be saved as the PSWA, make sure it has the high bit
1322 set. */
1323 literals[0] |= 0x80000000;
1324 /* Stuff the literals into the buffer. */
1325 for (i = 0; i < 4; i++) {
1326 uint32_t lit = literals[i];
1327 memcpy (&buf[sizeof buf - 16 + i * 4], &lit, 4);
1328 }
1329 append_insns (&buildaddr, sizeof buf - bufpos, buf + bufpos);
1330 append_insns (&buildaddr, sizeof s390_ft_main_31, s390_ft_main_31);
1331 }
1332
1333 /* Restore FRs or VRs. */
1334 if (has_vx)
1335 append_insns (&buildaddr, sizeof s390_ft_exit_vr, s390_ft_exit_vr);
1336 else
1337 append_insns (&buildaddr, sizeof s390_ft_exit_fr, s390_ft_exit_fr);
1338
1339 /* Restore misc registers. */
1340 append_insns (&buildaddr, sizeof s390_ft_exit_misc, s390_ft_exit_misc);
1341
1342 /* Restore the GPRs. */
1343 if (is_zarch)
1344 append_insns (&buildaddr, sizeof s390_ft_exit_gpr_zarch,
1345 s390_ft_exit_gpr_zarch);
1346 else
1347 append_insns (&buildaddr, sizeof s390_ft_exit_gpr_esa,
1348 s390_ft_exit_gpr_esa);
1349
1350 /* Now, adjust the original instruction to execute in the jump
1351 pad. */
1352 *adjusted_insn_addr = buildaddr;
1353 if (s390_relocate_instruction (&buildaddr, tpaddr, is_64))
1354 {
1355 sprintf (err, "E.Could not relocate instruction for tracepoint.");
1356 return 1;
1357 }
1358 *adjusted_insn_addr_end = buildaddr;
1359
1360 /* Finally, write a jump back to the program. */
1361
1362 loffset = (tpaddr + orig_size) - buildaddr;
1363 loffset >>= 1;
1364 offset = loffset;
1365 if (is_64 && offset != loffset)
1366 {
1367 sprintf (err,
1368 "E.Jump back from jump pad too far from tracepoint "
1369 "(offset 0x%" PRIx64 " > int33).", loffset);
1370 return 1;
1371 }
1372 memcpy (jbuf + 2, &offset, 4);
1373 append_insns (&buildaddr, sizeof jbuf, jbuf);
1374
1375 /* The jump pad is now built. Wire in a jump to our jump pad. This
1376 is always done last (by our caller actually), so that we can
1377 install fast tracepoints with threads running. This relies on
1378 the agent's atomic write support. */
1379 loffset = *jump_entry - tpaddr;
1380 loffset >>= 1;
1381 offset = loffset;
1382 if (is_64 && offset != loffset)
1383 {
1384 sprintf (err,
1385 "E.Jump back from jump pad too far from tracepoint "
1386 "(offset 0x%" PRIx64 " > int33).", loffset);
1387 return 1;
1388 }
1389 memcpy (jbuf + 2, &offset, 4);
1390 memcpy (jjump_pad_insn, jbuf, sizeof jbuf);
1391 *jjump_pad_insn_size = sizeof jbuf;
1392
1393 /* Return the end address of our pad. */
1394 *jump_entry = buildaddr;
1395
1396 return 0;
1397}
1398
1399/* Implementation of linux_target_ops method
1400 "get_min_fast_tracepoint_insn_len". */
1401
1402static int
1403s390_get_min_fast_tracepoint_insn_len (void)
1404{
1405 /* We only support using 6-byte jumps to reach the tracepoint code.
1406 If the tracepoint buffer were allocated sufficiently close (64kiB)
1407 to the executable code, and the traced instruction itself was close
1408 enough to the beginning, we could use 4-byte jumps, but this doesn't
1409 seem to be worth the effort. */
1410 return 6;
1411}
1412
1413/* Implementation of linux_target_ops method "get_ipa_tdesc_idx". */
1414
1415static int
1416s390_get_ipa_tdesc_idx (void)
1417{
1418 struct regcache *regcache = get_thread_regcache (current_thread, 0);
1419 const struct target_desc *tdesc = regcache->tdesc;
1420
1421#ifdef __s390x__
1422 if (tdesc == tdesc_s390x_linux64)
1423 return S390_TDESC_64;
1424 if (tdesc == tdesc_s390x_linux64v1)
1425 return S390_TDESC_64V1;
1426 if (tdesc == tdesc_s390x_linux64v2)
1427 return S390_TDESC_64V2;
1428 if (tdesc == tdesc_s390x_te_linux64)
1429 return S390_TDESC_TE;
1430 if (tdesc == tdesc_s390x_vx_linux64)
1431 return S390_TDESC_VX;
1432 if (tdesc == tdesc_s390x_tevx_linux64)
1433 return S390_TDESC_TEVX;
1434#endif
1435
1436 if (tdesc == tdesc_s390_linux32)
1437 return S390_TDESC_32;
1438 if (tdesc == tdesc_s390_linux32v1)
1439 return S390_TDESC_32V1;
1440 if (tdesc == tdesc_s390_linux32v2)
1441 return S390_TDESC_32V2;
1442 if (tdesc == tdesc_s390_linux64)
1443 return S390_TDESC_64;
1444 if (tdesc == tdesc_s390_linux64v1)
1445 return S390_TDESC_64V1;
1446 if (tdesc == tdesc_s390_linux64v2)
1447 return S390_TDESC_64V2;
1448 if (tdesc == tdesc_s390_te_linux64)
1449 return S390_TDESC_TE;
1450 if (tdesc == tdesc_s390_vx_linux64)
1451 return S390_TDESC_VX;
1452 if (tdesc == tdesc_s390_tevx_linux64)
1453 return S390_TDESC_TEVX;
1454
1455 return 0;
1456}
1457
f39e8743
MK
1458/* Appends given buffer to current_insn_ptr in the target. */
1459
1460static void
1461add_insns (const unsigned char *start, int len)
1462{
1463 CORE_ADDR buildaddr = current_insn_ptr;
1464
1465 if (debug_threads)
1466 debug_printf ("Adding %d bytes of insn at %s\n",
1467 len, paddress (buildaddr));
1468
1469 append_insns (&buildaddr, len, start);
1470 current_insn_ptr = buildaddr;
1471}
1472
1473/* Register usage in emit:
1474
1475 - %r0, %r1: temp
1476 - %r2: top of stack (high word for 31-bit)
1477 - %r3: low word of top of stack (for 31-bit)
1478 - %r4, %r5: temp
1479 - %r6, %r7, %r8: don't use
1480 - %r9: saved arg1
1481 - %r10: saved arg2
1482 - %r11: frame pointer
1483 - %r12: saved top of stack for void_call_2 (high word for 31-bit)
1484 - %r13: low word of saved top of stack (for 31-bit)
1485 - %r14: return address for calls
1486 - %r15: stack pointer
1487
1488 */
1489
1490/* The "emit_prologue" emit_ops method for s390. */
1491
1492static void
1493s390_emit_prologue (void)
1494{
1495 static const unsigned char buf[] = {
1496 0x90, 0x9f, 0xf0, 0x24, /* stm %r9, %r15, 0x24(%r15) */
1497 0x18, 0x92, /* lr %r9, %r2 */
1498 0x18, 0xa3, /* lr %r10, %r3 */
1499 0x18, 0xbf, /* lr %r11, %r15 */
1500 };
1501 add_insns (buf, sizeof buf);
1502}
1503
1504/* The "emit_epilogue" emit_ops method for s390. */
1505
1506static void
1507s390_emit_epilogue (void)
1508{
1509 static const unsigned char buf[] = {
1510 0x90, 0x23, 0xa0, 0x00, /* stm %r2, %r3, 0(%r10) */
1511 0xa7, 0x28, 0x00, 0x00, /* lhi %r2, 0 */
1512 0x98, 0x9f, 0xb0, 0x24, /* lm %r9, %r15, 0x24(%r11) */
1513 0x07, 0xfe, /* br %r14 */
1514 };
1515 add_insns (buf, sizeof buf);
1516}
1517
1518/* The "emit_add" emit_ops method for s390. */
1519
1520static void
1521s390_emit_add (void)
1522{
1523 static const unsigned char buf[] = {
1524 0x5e, 0x30, 0xf0, 0x04, /* al %r3, 4(%r15) */
1525 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x98, /* al %r2, 0(%r15) */
1526 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1527 };
1528 add_insns (buf, sizeof buf);
1529}
1530
1531/* The "emit_sub" emit_ops method for s390. */
1532
1533static void
1534s390_emit_sub (void)
1535{
1536 static const unsigned char buf[] = {
1537 0x98, 0x45, 0xf0, 0x00, /* lm %r4, %r5, 0(%r15) */
1538 0x1f, 0x53, /* slr %r5, %r3 */
1539 0xb9, 0x99, 0x00, 0x42, /* slbr %r4, %r2 */
1540 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1541 0x18, 0x35, /* lr %r3, %r5 */
1542 0x18, 0x24, /* lr %r2, %r4 */
1543 };
1544 add_insns (buf, sizeof buf);
1545}
1546
1547/* The "emit_mul" emit_ops method for s390. */
1548
1549static void
1550s390_emit_mul (void)
1551{
1552 emit_error = 1;
1553}
1554
1555/* The "emit_lsh" emit_ops method for s390. */
1556
1557static void
1558s390_emit_lsh (void)
1559{
1560 static const unsigned char buf[] = {
1561 0x18, 0x43, /* lr %r4, %r3 */
1562 0x98, 0x23, 0xf0, 0x00, /* lm %r2, %r3, 0(%r15) */
1563 0x8d, 0x20, 0x40, 0x00, /* sldl %r2, 0(%r4) */
1564 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1565 };
1566 add_insns (buf, sizeof buf);
1567}
1568
1569/* The "emit_rsh_signed" emit_ops method for s390. */
1570
1571static void
1572s390_emit_rsh_signed (void)
1573{
1574 static const unsigned char buf[] = {
1575 0x18, 0x43, /* lr %r4, %r3 */
1576 0x98, 0x23, 0xf0, 0x00, /* lm %r2, %r3, 0(%r15) */
1577 0x8e, 0x20, 0x40, 0x00, /* srda %r2, 0(%r4) */
1578 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1579 };
1580 add_insns (buf, sizeof buf);
1581}
1582
1583/* The "emit_rsh_unsigned" emit_ops method for s390. */
1584
1585static void
1586s390_emit_rsh_unsigned (void)
1587{
1588 static const unsigned char buf[] = {
1589 0x18, 0x43, /* lr %r4, %r3 */
1590 0x98, 0x23, 0xf0, 0x00, /* lm %r2, %r3, 0(%r15) */
1591 0x8c, 0x20, 0x40, 0x00, /* srdl %r2, 0(%r4) */
1592 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1593 };
1594 add_insns (buf, sizeof buf);
1595}
1596
1597/* The "emit_ext" emit_ops method for s390. */
1598
1599static void
1600s390_emit_ext (int arg)
1601{
1602 unsigned char buf[] = {
1603 0x8d, 0x20, 0x00, 64 - arg, /* sldl %r2, <64-arg> */
1604 0x8e, 0x20, 0x00, 64 - arg, /* srda %r2, <64-arg> */
1605 };
1606 add_insns (buf, sizeof buf);
1607}
1608
1609/* The "emit_log_not" emit_ops method for s390. */
1610
1611static void
1612s390_emit_log_not (void)
1613{
1614 static const unsigned char buf[] = {
1615 0x16, 0x23, /* or %r2, %r3 */
1616 0xa7, 0x28, 0x00, 0x00, /* lhi %r2, 0 */
1617 0xa7, 0x38, 0x00, 0x00, /* lhi %r3, 0 */
1618 0xa7, 0x74, 0x00, 0x04, /* jne .Lskip */
1619 0xa7, 0x38, 0x00, 0x01, /* lhi %r3, 1 */
1620 /* .Lskip: */
1621 };
1622 add_insns (buf, sizeof buf);
1623}
1624
1625/* The "emit_bit_and" emit_ops method for s390. */
1626
1627static void
1628s390_emit_bit_and (void)
1629{
1630 static const unsigned char buf[] = {
1631 0x54, 0x20, 0xf0, 0x00, /* n %r2, 0(%r15) */
1632 0x54, 0x30, 0xf0, 0x04, /* n %r3, 4(%r15) */
1633 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1634 };
1635 add_insns (buf, sizeof buf);
1636}
1637
1638/* The "emit_bit_or" emit_ops method for s390. */
1639
1640static void
1641s390_emit_bit_or (void)
1642{
1643 static const unsigned char buf[] = {
1644 0x56, 0x20, 0xf0, 0x00, /* o %r2, 0(%r15) */
1645 0x56, 0x30, 0xf0, 0x04, /* o %r3, 4(%r15) */
1646 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1647 };
1648 add_insns (buf, sizeof buf);
1649}
1650
1651/* The "emit_bit_xor" emit_ops method for s390. */
1652
1653static void
1654s390_emit_bit_xor (void)
1655{
1656 static const unsigned char buf[] = {
1657 0x57, 0x20, 0xf0, 0x00, /* x %r2, 0(%r15) */
1658 0x57, 0x30, 0xf0, 0x04, /* x %r3, 4(%r15) */
1659 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1660 };
1661 add_insns (buf, sizeof buf);
1662}
1663
1664/* The "emit_bit_not" emit_ops method for s390. */
1665
1666static void
1667s390_emit_bit_not (void)
1668{
1669 static const unsigned char buf[] = {
1670 0xa7, 0x48, 0xff, 0xff, /* lhi %r4, -1 */
1671 0x17, 0x24, /* xr %r2, %r4 */
1672 0x17, 0x34, /* xr %r3, %r4 */
1673 };
1674 add_insns (buf, sizeof buf);
1675}
1676
1677/* The "emit_equal" emit_ops method for s390. */
1678
1679static void
1680s390_emit_equal (void)
1681{
1682 s390_emit_bit_xor ();
1683 s390_emit_log_not ();
1684}
1685
1686/* The "emit_less_signed" emit_ops method for s390. */
1687
1688static void
1689s390_emit_less_signed (void)
1690{
1691 static const unsigned char buf[] = {
1692 0x59, 0x20, 0xf0, 0x00, /* c %r2, 0(%r15) */
1693 0xa7, 0x24, 0x00, 0x0c, /* jh .Lless */
1694 0xa7, 0x44, 0x00, 0x06, /* jl .Lhigh */
1695 0x55, 0x30, 0xf0, 0x04, /* cl %r3, 4(%r15) */
1696 0xa7, 0x24, 0x00, 0x06, /* jh .Lless */
1697 /* .Lhigh: */
1698 0xa7, 0x38, 0x00, 0x00, /* lhi %r3, 0 */
1699 0xa7, 0xf4, 0x00, 0x04, /* j .Lend */
1700 /* .Lless: */
1701 0xa7, 0x38, 0x00, 0x01, /* lhi %r3, 1 */
1702 /* .Lend: */
1703 0xa7, 0x28, 0x00, 0x00, /* lhi %r2, 0 */
1704 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1705 };
1706 add_insns (buf, sizeof buf);
1707}
1708
1709/* The "emit_less_unsigned" emit_ops method for s390. */
1710
1711static void
1712s390_emit_less_unsigned (void)
1713{
1714 static const unsigned char buf[] = {
1715 0x55, 0x20, 0xf0, 0x00, /* cl %r2, 0(%r15) */
1716 0xa7, 0x24, 0x00, 0x0c, /* jh .Lless */
1717 0xa7, 0x44, 0x00, 0x06, /* jl .Lhigh */
1718 0x55, 0x30, 0xf0, 0x04, /* cl %r3, 4(%r15) */
1719 0xa7, 0x24, 0x00, 0x06, /* jh .Lless */
1720 /* .Lhigh: */
1721 0xa7, 0x38, 0x00, 0x00, /* lhi %r3, 0 */
1722 0xa7, 0xf4, 0x00, 0x04, /* j .Lend */
1723 /* .Lless: */
1724 0xa7, 0x38, 0x00, 0x01, /* lhi %r3, 1 */
1725 /* .Lend: */
1726 0xa7, 0x28, 0x00, 0x00, /* lhi %r2, 0 */
1727 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1728 };
1729 add_insns (buf, sizeof buf);
1730}
1731
1732/* The "emit_ref" emit_ops method for s390. */
1733
1734static void
1735s390_emit_ref (int size)
1736{
1737 static const unsigned char buf1[] = {
1738 0xa7, 0x28, 0x00, 0x00, /* lhi %r2, 0 */
1739 0x43, 0x30, 0x30, 0x00, /* ic %r3, 0(%r3) */
1740 };
1741 static const unsigned char buf2[] = {
1742 0xa7, 0x28, 0x00, 0x00, /* lhi %r2, 0 */
1743 0x48, 0x30, 0x30, 0x00, /* lh %r3, 0(%r3) */
1744 };
1745 static const unsigned char buf4[] = {
1746 0xa7, 0x28, 0x00, 0x00, /* lhi %r2, 0 */
1747 0x58, 0x30, 0x30, 0x00, /* l %r3, 0(%r3) */
1748 };
1749 static const unsigned char buf8[] = {
1750 0x98, 0x23, 0x30, 0x00, /* lm %r2, %r3, 0(%r3) */
1751 };
1752 switch (size)
1753 {
1754 case 1:
1755 add_insns (buf1, sizeof buf1);
1756 break;
1757 case 2:
1758 add_insns (buf2, sizeof buf2);
1759 break;
1760 case 4:
1761 add_insns (buf4, sizeof buf4);
1762 break;
1763 case 8:
1764 add_insns (buf8, sizeof buf8);
1765 break;
1766 default:
1767 emit_error = 1;
1768 }
1769}
1770
1771/* The "emit_if_goto" emit_ops method for s390. */
1772
1773static void
1774s390_emit_if_goto (int *offset_p, int *size_p)
1775{
1776 static const unsigned char buf[] = {
1777 0x16, 0x23, /* or %r2, %r3 */
1778 0x98, 0x23, 0xf0, 0x00, /* lm %r2, %r3, 0(%r15) */
1779 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1780 0xc0, 0x74, 0x00, 0x00, 0x00, 0x00 /* jgne <fillme> */
1781 };
1782 add_insns (buf, sizeof buf);
1783 if (offset_p)
1784 *offset_p = 12;
1785 if (size_p)
1786 *size_p = 4;
1787}
1788
1789/* The "emit_goto" emit_ops method for s390 and s390x. */
1790
1791static void
1792s390_emit_goto (int *offset_p, int *size_p)
1793{
1794 static const unsigned char buf[] = {
1795 0xc0, 0xf4, 0x00, 0x00, 0x00, 0x00, /* jg <fillme> */
1796 };
1797 add_insns (buf, sizeof buf);
1798 if (offset_p)
1799 *offset_p = 2;
1800 if (size_p)
1801 *size_p = 4;
1802}
1803
1804/* The "write_goto_address" emit_ops method for s390 and s390x. */
1805
1806static void
1807s390_write_goto_address (CORE_ADDR from, CORE_ADDR to, int size)
1808{
1809 long diff = ((long) (to - (from - 2))) / 2;
1810 int sdiff = diff;
1811 unsigned char buf[sizeof sdiff];
1812
1813 /* We're only doing 4-byte sizes at the moment. */
1814 if (size != sizeof sdiff || sdiff != diff)
1815 {
1816 emit_error = 1;
1817 return;
1818 }
1819
1820 memcpy (buf, &sdiff, sizeof sdiff);
1821 write_inferior_memory (from, buf, sizeof sdiff);
1822}
1823
1824/* Preparation for emitting a literal pool of given size. Loads the address
1825 of the pool into %r1, and jumps over it. Called should emit the pool data
1826 immediately afterwards. Used for both s390 and s390x. */
1827
1828static void
1829s390_emit_litpool (int size)
1830{
1831 static const unsigned char nop[] = {
1832 0x07, 0x07,
1833 };
1834 unsigned char buf[] = {
1835 0xa7, 0x15, 0x00, (size + 4) / 2, /* bras %r1, .Lend+size */
1836 /* .Lend: */
1837 };
1838 if (size == 4)
1839 {
1840 /* buf needs to start at even halfword for litpool to be aligned */
1841 if (current_insn_ptr & 2)
1842 add_insns (nop, sizeof nop);
1843 }
1844 else
1845 {
1846 while ((current_insn_ptr & 6) != 4)
1847 add_insns (nop, sizeof nop);
1848 }
1849 add_insns (buf, sizeof buf);
1850}
1851
1852/* The "emit_const" emit_ops method for s390. */
1853
1854static void
1855s390_emit_const (LONGEST num)
1856{
1857 unsigned long long n = num;
1858 unsigned char buf_s[] = {
1859 0xa7, 0x38, num >> 8, num, /* lhi %r3, <num> */
1860 0x17, 0x22, /* xr %r2, %r2 */
1861 };
1862 static const unsigned char buf_l[] = {
1863 0x98, 0x23, 0x10, 0x00, /* lm %r2, %r3, 0(%r1) */
1864 };
1865 if (num < 0x8000 && num >= 0)
1866 {
1867 add_insns (buf_s, sizeof buf_s);
1868 }
1869 else
1870 {
1871 s390_emit_litpool (8);
1872 add_insns ((unsigned char *) &n, sizeof n);
1873 add_insns (buf_l, sizeof buf_l);
1874 }
1875}
1876
1877/* The "emit_call" emit_ops method for s390. */
1878
1879static void
1880s390_emit_call (CORE_ADDR fn)
1881{
1882 unsigned int n = fn;
1883 static const unsigned char buf[] = {
1884 0x58, 0x10, 0x10, 0x00, /* l %r1, 0(%r1) */
1885 0xa7, 0xfa, 0xff, 0xa0, /* ahi %r15, -0x60 */
1886 0x0d, 0xe1, /* basr %r14, %r1 */
1887 0xa7, 0xfa, 0x00, 0x60, /* ahi %r15, 0x60 */
1888 };
1889 s390_emit_litpool (4);
1890 add_insns ((unsigned char *) &n, sizeof n);
1891 add_insns (buf, sizeof buf);
1892}
1893
1894/* The "emit_reg" emit_ops method for s390. */
1895
1896static void
1897s390_emit_reg (int reg)
1898{
1899 unsigned char bufpre[] = {
1900 0x18, 0x29, /* lr %r2, %r9 */
1901 0xa7, 0x38, reg >> 8, reg, /* lhi %r3, <reg> */
1902 };
1903 add_insns (bufpre, sizeof bufpre);
1904 s390_emit_call (get_raw_reg_func_addr ());
1905}
1906
1907/* The "emit_pop" emit_ops method for s390. */
1908
1909static void
1910s390_emit_pop (void)
1911{
1912 static const unsigned char buf[] = {
1913 0x98, 0x23, 0xf0, 0x00, /* lm %r2, %r3, 0(%r15) */
1914 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1915 };
1916 add_insns (buf, sizeof buf);
1917}
1918
1919/* The "emit_stack_flush" emit_ops method for s390. */
1920
1921static void
1922s390_emit_stack_flush (void)
1923{
1924 static const unsigned char buf[] = {
1925 0xa7, 0xfa, 0xff, 0xf8, /* ahi %r15, -8 */
1926 0x90, 0x23, 0xf0, 0x00, /* stm %r2, %r3, 0(%r15) */
1927 };
1928 add_insns (buf, sizeof buf);
1929}
1930
1931/* The "emit_zero_ext" emit_ops method for s390. */
1932
1933static void
1934s390_emit_zero_ext (int arg)
1935{
1936 unsigned char buf[] = {
1937 0x8d, 0x20, 0x00, 64 - arg, /* sldl %r2, <64-arg> */
1938 0x8c, 0x20, 0x00, 64 - arg, /* srdl %r2, <64-arg> */
1939 };
1940 add_insns (buf, sizeof buf);
1941}
1942
1943/* The "emit_swap" emit_ops method for s390. */
1944
1945static void
1946s390_emit_swap (void)
1947{
1948 static const unsigned char buf[] = {
1949 0x98, 0x45, 0xf0, 0x00, /* lm %r4, %r5, 0(%r15) */
1950 0x90, 0x23, 0xf0, 0x00, /* stm %r2, %r3, 0(%r15) */
1951 0x18, 0x24, /* lr %r2, %r4 */
1952 0x18, 0x35, /* lr %r3, %r5 */
1953 };
1954 add_insns (buf, sizeof buf);
1955}
1956
1957/* The "emit_stack_adjust" emit_ops method for s390. */
1958
1959static void
1960s390_emit_stack_adjust (int n)
1961{
1962 unsigned char buf[] = {
1963 0xa7, 0xfa, n * 8 >> 8, n * 8, /* ahi %r15, 8*n */
1964 };
1965 add_insns (buf, sizeof buf);
1966}
1967
1968/* Sets %r2 to a 32-bit constant. */
1969
1970static void
1971s390_emit_set_r2 (int arg1)
1972{
1973 unsigned char buf_s[] = {
1974 0xa7, 0x28, arg1 >> 8, arg1, /* lhi %r2, <arg1> */
1975 };
1976 static const unsigned char buf_l[] = {
1977 0x58, 0x20, 0x10, 0x00, /* l %r2, 0(%r1) */
1978 };
1979 if (arg1 < 0x8000 && arg1 >= -0x8000)
1980 {
1981 add_insns (buf_s, sizeof buf_s);
1982 }
1983 else
1984 {
1985 s390_emit_litpool (4);
1986 add_insns ((unsigned char *) &arg1, sizeof arg1);
1987 add_insns (buf_l, sizeof buf_l);
1988 }
1989}
1990
1991/* The "emit_int_call_1" emit_ops method for s390. */
1992
1993static void
1994s390_emit_int_call_1 (CORE_ADDR fn, int arg1)
1995{
1996 /* FN's prototype is `LONGEST(*fn)(int)'. */
1997 s390_emit_set_r2 (arg1);
1998 s390_emit_call (fn);
1999}
2000
2001/* The "emit_void_call_2" emit_ops method for s390. */
2002
2003static void
2004s390_emit_void_call_2 (CORE_ADDR fn, int arg1)
2005{
2006 /* FN's prototype is `void(*fn)(int,LONGEST)'. */
2007 static const unsigned char buf[] = {
2008 0x18, 0xc2, /* lr %r12, %r2 */
2009 0x18, 0xd3, /* lr %r13, %r3 */
2010 0x18, 0x43, /* lr %r4, %r3 */
2011 0x18, 0x32, /* lr %r3, %r2 */
2012 };
2013 static const unsigned char buf2[] = {
2014 0x18, 0x2c, /* lr %r2, %r12 */
2015 0x18, 0x3d, /* lr %r3, %r13 */
2016 };
2017 add_insns (buf, sizeof buf);
2018 s390_emit_set_r2 (arg1);
2019 s390_emit_call (fn);
2020 add_insns (buf2, sizeof buf2);
2021}
2022
2023/* The "emit_eq_goto" emit_ops method for s390. */
2024
782c1122 2025static void
f39e8743
MK
2026s390_emit_eq_goto (int *offset_p, int *size_p)
2027{
2028 static const unsigned char buf[] = {
2029 0x57, 0x20, 0xf0, 0x00, /* x %r2, 0(%r15) */
2030 0x57, 0x30, 0xf0, 0x04, /* x %r3, 4(%r15) */
2031 0x16, 0x23, /* or %r2, %r3 */
2032 0x98, 0x23, 0xf0, 0x08, /* lm %r2, %r3, 8(%r15) */
2033 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2034 0xc0, 0x84, 0x00, 0x00, 0x00, 0x00, /* jge <fillme> */
2035 };
2036 add_insns (buf, sizeof buf);
2037 if (offset_p)
2038 *offset_p = 20;
2039 if (size_p)
2040 *size_p = 4;
2041}
2042
2043/* The "emit_ne_goto" emit_ops method for s390. */
2044
782c1122 2045static void
f39e8743
MK
2046s390_emit_ne_goto (int *offset_p, int *size_p)
2047{
2048 static const unsigned char buf[] = {
2049 0x57, 0x20, 0xf0, 0x00, /* x %r2, 0(%r15) */
2050 0x57, 0x30, 0xf0, 0x04, /* x %r3, 4(%r15) */
2051 0x16, 0x23, /* or %r2, %r3 */
2052 0x98, 0x23, 0xf0, 0x08, /* lm %r2, %r3, 8(%r15) */
2053 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2054 0xc0, 0x74, 0x00, 0x00, 0x00, 0x00, /* jgne <fillme> */
2055 };
2056 add_insns (buf, sizeof buf);
2057 if (offset_p)
2058 *offset_p = 20;
2059 if (size_p)
2060 *size_p = 4;
2061}
2062
2063/* The "emit_lt_goto" emit_ops method for s390. */
2064
782c1122 2065static void
f39e8743
MK
2066s390_emit_lt_goto (int *offset_p, int *size_p)
2067{
2068 static const unsigned char buf[] = {
2069 0x59, 0x20, 0xf0, 0x00, /* c %r2, 0(%r15) */
2070 0xa7, 0x24, 0x00, 0x0e, /* jh .Ltrue */
2071 0xa7, 0x44, 0x00, 0x06, /* jl .Lfalse */
2072 0x55, 0x30, 0xf0, 0x04, /* cl %r3, 4(%r15) */
2073 0xa7, 0x24, 0x00, 0x08, /* jh .Ltrue */
2074 /* .Lfalse: */
2075 0x98, 0x23, 0xf0, 0x08, /* lm %r2, %r3, 8(%r15) */
2076 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2077 0xa7, 0xf4, 0x00, 0x09, /* j .Lend */
2078 /* .Ltrue: */
2079 0x98, 0x23, 0xf0, 0x08, /* lm %r2, %r3, 8(%r15) */
2080 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2081 0xc0, 0xf4, 0x00, 0x00, 0x00, 0x00, /* jg <fillme> */
2082 /* .Lend: */
2083 };
2084 add_insns (buf, sizeof buf);
2085 if (offset_p)
2086 *offset_p = 42;
2087 if (size_p)
2088 *size_p = 4;
2089}
2090
2091/* The "emit_le_goto" emit_ops method for s390. */
2092
782c1122 2093static void
f39e8743
MK
2094s390_emit_le_goto (int *offset_p, int *size_p)
2095{
2096 static const unsigned char buf[] = {
2097 0x59, 0x20, 0xf0, 0x00, /* c %r2, 0(%r15) */
2098 0xa7, 0x24, 0x00, 0x0e, /* jh .Ltrue */
2099 0xa7, 0x44, 0x00, 0x06, /* jl .Lfalse */
2100 0x55, 0x30, 0xf0, 0x04, /* cl %r3, 4(%r15) */
2101 0xa7, 0xa4, 0x00, 0x08, /* jhe .Ltrue */
2102 /* .Lfalse: */
2103 0x98, 0x23, 0xf0, 0x08, /* lm %r2, %r3, 8(%r15) */
2104 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2105 0xa7, 0xf4, 0x00, 0x09, /* j .Lend */
2106 /* .Ltrue: */
2107 0x98, 0x23, 0xf0, 0x08, /* lm %r2, %r3, 8(%r15) */
2108 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2109 0xc0, 0xf4, 0x00, 0x00, 0x00, 0x00, /* jg <fillme> */
2110 /* .Lend: */
2111 };
2112 add_insns (buf, sizeof buf);
2113 if (offset_p)
2114 *offset_p = 42;
2115 if (size_p)
2116 *size_p = 4;
2117}
2118
2119/* The "emit_gt_goto" emit_ops method for s390. */
2120
782c1122 2121static void
f39e8743
MK
2122s390_emit_gt_goto (int *offset_p, int *size_p)
2123{
2124 static const unsigned char buf[] = {
2125 0x59, 0x20, 0xf0, 0x00, /* c %r2, 0(%r15) */
2126 0xa7, 0x44, 0x00, 0x0e, /* jl .Ltrue */
2127 0xa7, 0x24, 0x00, 0x06, /* jh .Lfalse */
2128 0x55, 0x30, 0xf0, 0x04, /* cl %r3, 4(%r15) */
2129 0xa7, 0x44, 0x00, 0x08, /* jl .Ltrue */
2130 /* .Lfalse: */
2131 0x98, 0x23, 0xf0, 0x08, /* lm %r2, %r3, 8(%r15) */
2132 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2133 0xa7, 0xf4, 0x00, 0x09, /* j .Lend */
2134 /* .Ltrue: */
2135 0x98, 0x23, 0xf0, 0x08, /* lm %r2, %r3, 8(%r15) */
2136 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2137 0xc0, 0xf4, 0x00, 0x00, 0x00, 0x00, /* jg <fillme> */
2138 /* .Lend: */
2139 };
2140 add_insns (buf, sizeof buf);
2141 if (offset_p)
2142 *offset_p = 42;
2143 if (size_p)
2144 *size_p = 4;
2145}
2146
2147/* The "emit_ge_goto" emit_ops method for s390. */
2148
782c1122 2149static void
f39e8743
MK
2150s390_emit_ge_goto (int *offset_p, int *size_p)
2151{
2152 static const unsigned char buf[] = {
2153 0x59, 0x20, 0xf0, 0x00, /* c %r2, 0(%r15) */
2154 0xa7, 0x44, 0x00, 0x0e, /* jl .Ltrue */
2155 0xa7, 0x24, 0x00, 0x06, /* jh .Lfalse */
2156 0x55, 0x30, 0xf0, 0x04, /* cl %r3, 4(%r15) */
2157 0xa7, 0xc4, 0x00, 0x08, /* jle .Ltrue */
2158 /* .Lfalse: */
2159 0x98, 0x23, 0xf0, 0x08, /* lm %r2, %r3, 8(%r15) */
2160 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2161 0xa7, 0xf4, 0x00, 0x09, /* j .Lend */
2162 /* .Ltrue: */
2163 0x98, 0x23, 0xf0, 0x08, /* lm %r2, %r3, 8(%r15) */
2164 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2165 0xc0, 0xf4, 0x00, 0x00, 0x00, 0x00, /* jg <fillme> */
2166 /* .Lend: */
2167 };
2168 add_insns (buf, sizeof buf);
2169 if (offset_p)
2170 *offset_p = 42;
2171 if (size_p)
2172 *size_p = 4;
2173}
2174
2175/* The "emit_ops" structure for s390. Named _impl to avoid name
2176 collision with s390_emit_ops function. */
2177
782c1122 2178static struct emit_ops s390_emit_ops_impl =
f39e8743
MK
2179 {
2180 s390_emit_prologue,
2181 s390_emit_epilogue,
2182 s390_emit_add,
2183 s390_emit_sub,
2184 s390_emit_mul,
2185 s390_emit_lsh,
2186 s390_emit_rsh_signed,
2187 s390_emit_rsh_unsigned,
2188 s390_emit_ext,
2189 s390_emit_log_not,
2190 s390_emit_bit_and,
2191 s390_emit_bit_or,
2192 s390_emit_bit_xor,
2193 s390_emit_bit_not,
2194 s390_emit_equal,
2195 s390_emit_less_signed,
2196 s390_emit_less_unsigned,
2197 s390_emit_ref,
2198 s390_emit_if_goto,
2199 s390_emit_goto,
2200 s390_write_goto_address,
2201 s390_emit_const,
2202 s390_emit_call,
2203 s390_emit_reg,
2204 s390_emit_pop,
2205 s390_emit_stack_flush,
2206 s390_emit_zero_ext,
2207 s390_emit_swap,
2208 s390_emit_stack_adjust,
2209 s390_emit_int_call_1,
2210 s390_emit_void_call_2,
2211 s390_emit_eq_goto,
2212 s390_emit_ne_goto,
2213 s390_emit_lt_goto,
2214 s390_emit_le_goto,
2215 s390_emit_gt_goto,
2216 s390_emit_ge_goto
2217 };
2218
2219#ifdef __s390x__
2220
2221/* The "emit_prologue" emit_ops method for s390x. */
2222
2223static void
2224s390x_emit_prologue (void)
2225{
2226 static const unsigned char buf[] = {
2227 0xeb, 0x9f, 0xf0, 0x48, 0x00, 0x24, /* stmg %r9, %r15, 0x48(%r15) */
2228 0xb9, 0x04, 0x00, 0x92, /* lgr %r9, %r2 */
2229 0xb9, 0x04, 0x00, 0xa3, /* lgr %r10, %r3 */
2230 0xb9, 0x04, 0x00, 0xbf, /* lgr %r11, %r15 */
2231 };
2232 add_insns (buf, sizeof buf);
2233}
2234
2235/* The "emit_epilogue" emit_ops method for s390x. */
2236
2237static void
2238s390x_emit_epilogue (void)
2239{
2240 static const unsigned char buf[] = {
2241 0xe3, 0x20, 0xa0, 0x00, 0x00, 0x24, /* stg %r2, 0(%r10) */
2242 0xa7, 0x29, 0x00, 0x00, /* lghi %r2, 0 */
2243 0xeb, 0x9f, 0xf0, 0x48, 0x00, 0x04, /* lmg %r9, %r15, 0x48(%r15) */
2244 0x07, 0xfe, /* br %r14 */
2245 };
2246 add_insns (buf, sizeof buf);
2247}
2248
2249/* The "emit_add" emit_ops method for s390x. */
2250
2251static void
2252s390x_emit_add (void)
2253{
2254 static const unsigned char buf[] = {
2255 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x0a, /* alg %r2, 0(%r15) */
2256 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
2257 };
2258 add_insns (buf, sizeof buf);
2259}
2260
2261/* The "emit_sub" emit_ops method for s390x. */
2262
2263static void
2264s390x_emit_sub (void)
2265{
2266 static const unsigned char buf[] = {
2267 0xe3, 0x30, 0xf0, 0x00, 0x00, 0x04, /* lg %r3, 0(%r15) */
2268 0xb9, 0x0b, 0x00, 0x32, /* slgr %r3, %r2 */
2269 0xb9, 0x04, 0x00, 0x23, /* lgr %r2, %r3 */
2270 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
2271 };
2272 add_insns (buf, sizeof buf);
2273}
2274
2275/* The "emit_mul" emit_ops method for s390x. */
2276
2277static void
2278s390x_emit_mul (void)
2279{
2280 emit_error = 1;
2281}
2282
2283/* The "emit_lsh" emit_ops method for s390x. */
2284
2285static void
2286s390x_emit_lsh (void)
2287{
2288 static const unsigned char buf[] = {
2289 0xe3, 0x30, 0xf0, 0x00, 0x00, 0x04, /* lg %r3, 0(%r15) */
2290 0xeb, 0x23, 0x20, 0x00, 0x00, 0x0d, /* sllg %r2, %r3, 0(%r2) */
2291 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
2292 };
2293 add_insns (buf, sizeof buf);
2294}
2295
2296/* The "emit_rsh_signed" emit_ops method for s390x. */
2297
2298static void
2299s390x_emit_rsh_signed (void)
2300{
2301 static const unsigned char buf[] = {
2302 0xe3, 0x30, 0xf0, 0x00, 0x00, 0x04, /* lg %r3, 0(%r15) */
2303 0xeb, 0x23, 0x20, 0x00, 0x00, 0x0a, /* srag %r2, %r3, 0(%r2) */
2304 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
2305 };
2306 add_insns (buf, sizeof buf);
2307}
2308
2309/* The "emit_rsh_unsigned" emit_ops method for s390x. */
2310
2311static void
2312s390x_emit_rsh_unsigned (void)
2313{
2314 static const unsigned char buf[] = {
2315 0xe3, 0x30, 0xf0, 0x00, 0x00, 0x04, /* lg %r3, 0(%r15) */
2316 0xeb, 0x23, 0x20, 0x00, 0x00, 0x0c, /* srlg %r2, %r3, 0(%r2) */
2317 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
2318 };
2319 add_insns (buf, sizeof buf);
2320}
2321
2322/* The "emit_ext" emit_ops method for s390x. */
2323
2324static void
2325s390x_emit_ext (int arg)
2326{
2327 unsigned char buf[] = {
2328 0xeb, 0x22, 0x00, 64 - arg, 0x00, 0x0d, /* sllg %r2, %r2, <64-arg> */
2329 0xeb, 0x22, 0x00, 64 - arg, 0x00, 0x0a, /* srag %r2, %r2, <64-arg> */
2330 };
2331 add_insns (buf, sizeof buf);
2332}
2333
2334/* The "emit_log_not" emit_ops method for s390x. */
2335
2336static void
2337s390x_emit_log_not (void)
2338{
2339 static const unsigned char buf[] = {
2340 0xb9, 0x00, 0x00, 0x22, /* lpgr %r2, %r2 */
2341 0xa7, 0x2b, 0xff, 0xff, /* aghi %r2, -1 */
2342 0xeb, 0x22, 0x00, 0x3f, 0x00, 0x0c, /* srlg %r2, %r2, 63 */
2343 };
2344 add_insns (buf, sizeof buf);
2345}
2346
2347/* The "emit_bit_and" emit_ops method for s390x. */
2348
2349static void
2350s390x_emit_bit_and (void)
2351{
2352 static const unsigned char buf[] = {
2353 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x80, /* ng %r2, 0(%r15) */
2354 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
2355 };
2356 add_insns (buf, sizeof buf);
2357}
2358
2359/* The "emit_bit_or" emit_ops method for s390x. */
2360
2361static void
2362s390x_emit_bit_or (void)
2363{
2364 static const unsigned char buf[] = {
2365 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x81, /* og %r2, 0(%r15) */
2366 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
2367 };
2368 add_insns (buf, sizeof buf);
2369}
2370
2371/* The "emit_bit_xor" emit_ops method for s390x. */
2372
2373static void
2374s390x_emit_bit_xor (void)
2375{
2376 static const unsigned char buf[] = {
2377 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x82, /* xg %r2, 0(%r15) */
2378 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
2379 };
2380 add_insns (buf, sizeof buf);
2381}
2382
2383/* The "emit_bit_not" emit_ops method for s390x. */
2384
2385static void
2386s390x_emit_bit_not (void)
2387{
2388 static const unsigned char buf[] = {
2389 0xa7, 0x39, 0xff, 0xff, /* lghi %r3, -1 */
2390 0xb9, 0x82, 0x00, 0x23, /* xgr %r2, %r3 */
2391 };
2392 add_insns (buf, sizeof buf);
2393}
2394
2395/* The "emit_equal" emit_ops method for s390x. */
2396
2397static void
2398s390x_emit_equal (void)
2399{
2400 s390x_emit_bit_xor ();
2401 s390x_emit_log_not ();
2402}
2403
2404/* The "emit_less_signed" emit_ops method for s390x. */
2405
2406static void
2407s390x_emit_less_signed (void)
2408{
2409 static const unsigned char buf[] = {
2410 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20, /* cg %r2, 0(%r15) */
2411 0xa7, 0x29, 0x00, 0x01, /* lghi %r2, 1 */
2412 0xa7, 0x24, 0x00, 0x04, /* jh .Lend */
2413 0xa7, 0x29, 0x00, 0x00, /* lghi %r2, 0 */
2414 /* .Lend: */
2415 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
2416 };
2417 add_insns (buf, sizeof buf);
2418}
2419
2420/* The "emit_less_unsigned" emit_ops method for s390x. */
2421
2422static void
2423s390x_emit_less_unsigned (void)
2424{
2425 static const unsigned char buf[] = {
2426 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x21, /* clg %r2, 0(%r15) */
2427 0xa7, 0x29, 0x00, 0x01, /* lghi %r2, 1 */
2428 0xa7, 0x24, 0x00, 0x04, /* jh .Lend */
2429 0xa7, 0x29, 0x00, 0x00, /* lghi %r2, 0 */
2430 /* .Lend: */
2431 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
2432 };
2433 add_insns (buf, sizeof buf);
2434}
2435
2436/* The "emit_ref" emit_ops method for s390x. */
2437
2438static void
2439s390x_emit_ref (int size)
2440{
2441 static const unsigned char buf1[] = {
2442 0xe3, 0x20, 0x20, 0x00, 0x00, 0x90, /* llgc %r2, 0(%r2) */
2443 };
2444 static const unsigned char buf2[] = {
2445 0xe3, 0x20, 0x20, 0x00, 0x00, 0x91 /* llgh %r2, 0(%r2) */
2446 };
2447 static const unsigned char buf4[] = {
2448 0xe3, 0x20, 0x20, 0x00, 0x00, 0x16, /* llgf %r2, 0(%r2) */
2449 };
2450 static const unsigned char buf8[] = {
2451 0xe3, 0x20, 0x20, 0x00, 0x00, 0x04, /* lg %r2, 0(%r2) */
2452 };
2453 switch (size)
2454 {
2455 case 1:
2456 add_insns (buf1, sizeof buf1);
2457 break;
2458 case 2:
2459 add_insns (buf2, sizeof buf2);
2460 break;
2461 case 4:
2462 add_insns (buf4, sizeof buf4);
2463 break;
2464 case 8:
2465 add_insns (buf8, sizeof buf8);
2466 break;
2467 default:
2468 emit_error = 1;
2469 }
2470}
2471
2472/* The "emit_if_goto" emit_ops method for s390x. */
2473
2474static void
2475s390x_emit_if_goto (int *offset_p, int *size_p)
2476{
2477 static const unsigned char buf[] = {
2478 0xb9, 0x02, 0x00, 0x22, /* ltgr %r2, %r2 */
2479 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x04, /* lg %r2, 0(%r15) */
2480 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
2481 0xc0, 0x74, 0x00, 0x00, 0x00, 0x00, /* jgne <fillme> */
2482 };
2483 add_insns (buf, sizeof buf);
2484 if (offset_p)
2485 *offset_p = 16;
2486 if (size_p)
2487 *size_p = 4;
2488}
2489
2490/* The "emit_const" emit_ops method for s390x. */
2491
2492static void
2493s390x_emit_const (LONGEST num)
2494{
2495 unsigned long long n = num;
2496 unsigned char buf_s[] = {
2497 0xa7, 0x29, num >> 8, num, /* lghi %r2, <num> */
2498 };
2499 static const unsigned char buf_l[] = {
2500 0xe3, 0x20, 0x10, 0x00, 0x00, 0x04, /* lg %r2, 0(%r1) */
2501 };
2502 if (num < 0x8000 && num >= -0x8000)
2503 {
2504 add_insns (buf_s, sizeof buf_s);
2505 }
2506 else
2507 {
2508 s390_emit_litpool (8);
2509 add_insns ((unsigned char *) &n, sizeof n);
2510 add_insns (buf_l, sizeof buf_l);
2511 }
2512}
2513
2514/* The "emit_call" emit_ops method for s390x. */
2515
2516static void
2517s390x_emit_call (CORE_ADDR fn)
2518{
2519 unsigned long n = fn;
2520 static const unsigned char buf[] = {
2521 0xe3, 0x10, 0x10, 0x00, 0x00, 0x04, /* lg %r1, 0(%r1) */
2522 0xa7, 0xfb, 0xff, 0x60, /* aghi %r15, -0xa0 */
2523 0x0d, 0xe1, /* basr %r14, %r1 */
2524 0xa7, 0xfb, 0x00, 0xa0, /* aghi %r15, 0xa0 */
2525 };
2526 s390_emit_litpool (8);
2527 add_insns ((unsigned char *) &n, sizeof n);
2528 add_insns (buf, sizeof buf);
2529}
2530
2531/* The "emit_reg" emit_ops method for s390x. */
2532
2533static void
2534s390x_emit_reg (int reg)
2535{
2536 unsigned char buf[] = {
2537 0xb9, 0x04, 0x00, 0x29, /* lgr %r2, %r9 */
2538 0xa7, 0x39, reg >> 8, reg, /* lghi %r3, <reg> */
2539 };
2540 add_insns (buf, sizeof buf);
2541 s390x_emit_call (get_raw_reg_func_addr ());
2542}
2543
2544/* The "emit_pop" emit_ops method for s390x. */
2545
2546static void
2547s390x_emit_pop (void)
2548{
2549 static const unsigned char buf[] = {
2550 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x04, /* lg %r2, 0(%r15) */
2551 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
2552 };
2553 add_insns (buf, sizeof buf);
2554}
2555
2556/* The "emit_stack_flush" emit_ops method for s390x. */
2557
2558static void
2559s390x_emit_stack_flush (void)
2560{
2561 static const unsigned char buf[] = {
2562 0xa7, 0xfb, 0xff, 0xf8, /* aghi %r15, -8 */
2563 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x24, /* stg %r2, 0(%r15) */
2564 };
2565 add_insns (buf, sizeof buf);
2566}
2567
2568/* The "emit_zero_ext" emit_ops method for s390x. */
2569
2570static void
2571s390x_emit_zero_ext (int arg)
2572{
2573 unsigned char buf[] = {
2574 0xeb, 0x22, 0x00, 64 - arg, 0x00, 0x0d, /* sllg %r2, %r2, <64-arg> */
2575 0xeb, 0x22, 0x00, 64 - arg, 0x00, 0x0c, /* srlg %r2, %r2, <64-arg> */
2576 };
2577 add_insns (buf, sizeof buf);
2578}
2579
2580/* The "emit_swap" emit_ops method for s390x. */
2581
2582static void
2583s390x_emit_swap (void)
2584{
2585 static const unsigned char buf[] = {
2586 0xe3, 0x30, 0xf0, 0x00, 0x00, 0x04, /* lg %r3, 0(%r15) */
2587 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x24, /* stg %r2, 0(%r15) */
2588 0xb9, 0x04, 0x00, 0x23, /* lgr %r2, %r3 */
2589 };
2590 add_insns (buf, sizeof buf);
2591}
2592
2593/* The "emit_stack_adjust" emit_ops method for s390x. */
2594
2595static void
2596s390x_emit_stack_adjust (int n)
2597{
2598 unsigned char buf[] = {
2599 0xa7, 0xfb, n * 8 >> 8, n * 8, /* aghi %r15, 8*n */
2600 };
2601 add_insns (buf, sizeof buf);
2602}
2603
2604/* The "emit_int_call_1" emit_ops method for s390x. */
2605
2606static void
2607s390x_emit_int_call_1 (CORE_ADDR fn, int arg1)
2608{
2609 /* FN's prototype is `LONGEST(*fn)(int)'. */
2610 s390x_emit_const (arg1);
2611 s390x_emit_call (fn);
2612}
2613
2614/* The "emit_void_call_2" emit_ops method for s390x. */
2615
2616static void
2617s390x_emit_void_call_2 (CORE_ADDR fn, int arg1)
2618{
2619 /* FN's prototype is `void(*fn)(int,LONGEST)'. */
2620 static const unsigned char buf[] = {
2621 0xb9, 0x04, 0x00, 0x32, /* lgr %r3, %r2 */
2622 0xb9, 0x04, 0x00, 0xc2, /* lgr %r12, %r2 */
2623 };
2624 static const unsigned char buf2[] = {
2625 0xb9, 0x04, 0x00, 0x2c, /* lgr %r2, %r12 */
2626 };
2627 add_insns (buf, sizeof buf);
2628 s390x_emit_const (arg1);
2629 s390x_emit_call (fn);
2630 add_insns (buf2, sizeof buf2);
2631}
2632
2633/* The "emit_eq_goto" emit_ops method for s390x. */
2634
782c1122 2635static void
f39e8743
MK
2636s390x_emit_eq_goto (int *offset_p, int *size_p)
2637{
2638 static const unsigned char buf[] = {
2639 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20, /* cg %r2, 0(%r15) */
2640 0xe3, 0x20, 0xf0, 0x08, 0x00, 0x04, /* lg %r2, 8(%r15) */
2641 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2642 0xc0, 0x84, 0x00, 0x00, 0x00, 0x00, /* jge <fillme> */
2643 };
2644 add_insns (buf, sizeof buf);
2645 if (offset_p)
2646 *offset_p = 18;
2647 if (size_p)
2648 *size_p = 4;
2649}
2650
2651/* The "emit_ne_goto" emit_ops method for s390x. */
2652
782c1122 2653static void
f39e8743
MK
2654s390x_emit_ne_goto (int *offset_p, int *size_p)
2655{
2656 static const unsigned char buf[] = {
2657 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20, /* cg %r2, 0(%r15) */
2658 0xe3, 0x20, 0xf0, 0x08, 0x00, 0x04, /* lg %r2, 8(%r15) */
2659 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2660 0xc0, 0x74, 0x00, 0x00, 0x00, 0x00, /* jgne <fillme> */
2661 };
2662 add_insns (buf, sizeof buf);
2663 if (offset_p)
2664 *offset_p = 18;
2665 if (size_p)
2666 *size_p = 4;
2667}
2668
2669/* The "emit_lt_goto" emit_ops method for s390x. */
2670
782c1122 2671static void
f39e8743
MK
2672s390x_emit_lt_goto (int *offset_p, int *size_p)
2673{
2674 static const unsigned char buf[] = {
2675 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20, /* cg %r2, 0(%r15) */
2676 0xe3, 0x20, 0xf0, 0x08, 0x00, 0x04, /* lg %r2, 8(%r15) */
2677 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2678 0xc0, 0x24, 0x00, 0x00, 0x00, 0x00, /* jgh <fillme> */
2679 };
2680 add_insns (buf, sizeof buf);
2681 if (offset_p)
2682 *offset_p = 18;
2683 if (size_p)
2684 *size_p = 4;
2685}
2686
2687/* The "emit_le_goto" emit_ops method for s390x. */
2688
782c1122 2689static void
f39e8743
MK
2690s390x_emit_le_goto (int *offset_p, int *size_p)
2691{
2692 static const unsigned char buf[] = {
2693 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20, /* cg %r2, 0(%r15) */
2694 0xe3, 0x20, 0xf0, 0x08, 0x00, 0x04, /* lg %r2, 8(%r15) */
2695 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2696 0xc0, 0xa4, 0x00, 0x00, 0x00, 0x00, /* jghe <fillme> */
2697 };
2698 add_insns (buf, sizeof buf);
2699 if (offset_p)
2700 *offset_p = 18;
2701 if (size_p)
2702 *size_p = 4;
2703}
2704
2705/* The "emit_gt_goto" emit_ops method for s390x. */
2706
782c1122 2707static void
f39e8743
MK
2708s390x_emit_gt_goto (int *offset_p, int *size_p)
2709{
2710 static const unsigned char buf[] = {
2711 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20, /* cg %r2, 0(%r15) */
2712 0xe3, 0x20, 0xf0, 0x08, 0x00, 0x04, /* lg %r2, 8(%r15) */
2713 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2714 0xc0, 0x44, 0x00, 0x00, 0x00, 0x00, /* jgl <fillme> */
2715 };
2716 add_insns (buf, sizeof buf);
2717 if (offset_p)
2718 *offset_p = 18;
2719 if (size_p)
2720 *size_p = 4;
2721}
2722
2723/* The "emit_ge_goto" emit_ops method for s390x. */
2724
782c1122 2725static void
f39e8743
MK
2726s390x_emit_ge_goto (int *offset_p, int *size_p)
2727{
2728 static const unsigned char buf[] = {
2729 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20, /* cg %r2, 0(%r15) */
2730 0xe3, 0x20, 0xf0, 0x08, 0x00, 0x04, /* lg %r2, 8(%r15) */
2731 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2732 0xc0, 0xc4, 0x00, 0x00, 0x00, 0x00, /* jgle <fillme> */
2733 };
2734 add_insns (buf, sizeof buf);
2735 if (offset_p)
2736 *offset_p = 18;
2737 if (size_p)
2738 *size_p = 4;
2739}
2740
2741/* The "emit_ops" structure for s390x. */
2742
782c1122 2743static struct emit_ops s390x_emit_ops =
f39e8743
MK
2744 {
2745 s390x_emit_prologue,
2746 s390x_emit_epilogue,
2747 s390x_emit_add,
2748 s390x_emit_sub,
2749 s390x_emit_mul,
2750 s390x_emit_lsh,
2751 s390x_emit_rsh_signed,
2752 s390x_emit_rsh_unsigned,
2753 s390x_emit_ext,
2754 s390x_emit_log_not,
2755 s390x_emit_bit_and,
2756 s390x_emit_bit_or,
2757 s390x_emit_bit_xor,
2758 s390x_emit_bit_not,
2759 s390x_emit_equal,
2760 s390x_emit_less_signed,
2761 s390x_emit_less_unsigned,
2762 s390x_emit_ref,
2763 s390x_emit_if_goto,
2764 s390_emit_goto,
2765 s390_write_goto_address,
2766 s390x_emit_const,
2767 s390x_emit_call,
2768 s390x_emit_reg,
2769 s390x_emit_pop,
2770 s390x_emit_stack_flush,
2771 s390x_emit_zero_ext,
2772 s390x_emit_swap,
2773 s390x_emit_stack_adjust,
2774 s390x_emit_int_call_1,
2775 s390x_emit_void_call_2,
2776 s390x_emit_eq_goto,
2777 s390x_emit_ne_goto,
2778 s390x_emit_lt_goto,
2779 s390x_emit_le_goto,
2780 s390x_emit_gt_goto,
2781 s390x_emit_ge_goto
2782 };
2783#endif
2784
2785/* The "emit_ops" linux_target_ops method. */
2786
2787static struct emit_ops *
2788s390_emit_ops (void)
2789{
2790#ifdef __s390x__
2791 struct regcache *regcache = get_thread_regcache (current_thread, 0);
2792
2793 if (register_size (regcache->tdesc, 0) == 8)
2794 return &s390x_emit_ops;
2795 else
2796#endif
2797 return &s390_emit_ops_impl;
2798}
2799
2ec06d2e 2800struct linux_target_ops the_low_target = {
d61ddec4 2801 s390_arch_setup,
3aee8918 2802 s390_regs_info,
2ec06d2e
DJ
2803 s390_cannot_fetch_register,
2804 s390_cannot_store_register,
c14dfd32 2805 NULL, /* fetch_register */
b0ded00b
UW
2806 s390_get_pc,
2807 s390_set_pc,
dd373349
AT
2808 NULL, /* breakpoint_kind_from_pc */
2809 s390_sw_breakpoint_from_kind,
b0ded00b
UW
2810 NULL,
2811 s390_breakpoint_len,
2812 s390_breakpoint_at,
b00b61e1 2813 s390_supports_z_point_type,
ee1a7ae4
UW
2814 NULL,
2815 NULL,
2816 NULL,
2817 NULL,
2818 s390_collect_ptrace_register,
2819 s390_supply_ptrace_register,
7d00775e
AT
2820 NULL, /* siginfo_fixup */
2821 NULL, /* new_process */
04ec7890 2822 NULL, /* delete_process */
7d00775e 2823 NULL, /* new_thread */
466eecee 2824 NULL, /* delete_thread */
7d00775e
AT
2825 NULL, /* new_fork */
2826 NULL, /* prepare_to_resume */
2827 NULL, /* process_qsupported */
a4105d04 2828 s390_supports_tracepoints,
abd9baf9
MK
2829 s390_get_thread_area,
2830 s390_install_fast_tracepoint_jump_pad,
f39e8743 2831 s390_emit_ops,
abd9baf9 2832 s390_get_min_fast_tracepoint_insn_len,
7d00775e
AT
2833 NULL, /* supports_range_stepping */
2834 NULL, /* breakpoint_kind_from_current_state */
2835 s390_supports_hardware_single_step,
abd9baf9
MK
2836 NULL, /* get_syscall_trapinfo */
2837 s390_get_ipa_tdesc_idx,
2ec06d2e 2838};
3aee8918
PA
2839
2840void
2841initialize_low_arch (void)
2842{
2843 /* Initialize the Linux target descriptions. */
2844
2845 init_registers_s390_linux32 ();
2846 init_registers_s390_linux32v1 ();
2847 init_registers_s390_linux32v2 ();
2848 init_registers_s390_linux64 ();
2849 init_registers_s390_linux64v1 ();
2850 init_registers_s390_linux64v2 ();
4ac33720 2851 init_registers_s390_te_linux64 ();
bf2d68ab
AA
2852 init_registers_s390_vx_linux64 ();
2853 init_registers_s390_tevx_linux64 ();
ad339634 2854 init_registers_s390_gs_linux64 ();
abd9baf9 2855#ifdef __s390x__
3aee8918
PA
2856 init_registers_s390x_linux64 ();
2857 init_registers_s390x_linux64v1 ();
2858 init_registers_s390x_linux64v2 ();
4ac33720 2859 init_registers_s390x_te_linux64 ();
bf2d68ab
AA
2860 init_registers_s390x_vx_linux64 ();
2861 init_registers_s390x_tevx_linux64 ();
ad339634 2862 init_registers_s390x_gs_linux64 ();
abd9baf9 2863#endif
3aee8918
PA
2864
2865 initialize_regsets_info (&s390_regsets_info);
3aee8918 2866 initialize_regsets_info (&s390_regsets_info_3264);
3aee8918 2867}