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