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