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