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