[gdb/testsuite] Factor out proc with_lock
[binutils-gdb.git] / gdbserver / linux-s390-low.cc
blobee2c192609ac5efc1e5ebc3bd0d3d0dc29328973
1 /* GNU/Linux S/390 specific low level interface, for the remote server
2 for GDB.
3 Copyright (C) 2001-2024 Free Software Foundation, Inc.
5 This file is part of GDB.
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
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
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.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20 /* This file is used for both 31-bit and 64-bit S/390 systems. */
22 #include "linux-low.h"
23 #include "elf/common.h"
24 #include "ax.h"
25 #include "tracepoint.h"
27 #include <asm/ptrace.h>
28 #include "nat/gdb_ptrace.h"
29 #include <sys/uio.h>
30 #include <elf.h>
31 #include <inttypes.h>
33 #include "linux-s390-tdesc.h"
35 #ifndef HWCAP_S390_HIGH_GPRS
36 #define HWCAP_S390_HIGH_GPRS 512
37 #endif
39 #ifndef HWCAP_S390_TE
40 #define HWCAP_S390_TE 1024
41 #endif
43 #ifndef HWCAP_S390_VX
44 #define HWCAP_S390_VX 2048
45 #endif
47 #ifndef HWCAP_S390_GS
48 #define HWCAP_S390_GS 16384
49 #endif
51 #define s390_num_regs 52
53 /* Linux target op definitions for the S/390 architecture. */
55 class s390_target : public linux_process_target
57 public:
59 const regs_info *get_regs_info () override;
61 const gdb_byte *sw_breakpoint_from_kind (int kind, int *size) override;
63 bool supports_z_point_type (char z_type) override;
65 bool supports_tracepoints () override;
67 bool supports_fast_tracepoints () override;
69 int install_fast_tracepoint_jump_pad
70 (CORE_ADDR tpoint, CORE_ADDR tpaddr, CORE_ADDR collector,
71 CORE_ADDR lockaddr, ULONGEST orig_size, CORE_ADDR *jump_entry,
72 CORE_ADDR *trampoline, ULONGEST *trampoline_size,
73 unsigned char *jjump_pad_insn, ULONGEST *jjump_pad_insn_size,
74 CORE_ADDR *adjusted_insn_addr, CORE_ADDR *adjusted_insn_addr_end,
75 char *err) override;
77 int get_min_fast_tracepoint_insn_len () override;
79 void low_collect_ptrace_register (regcache *regcache, int regno,
80 char *buf) override;
82 void low_supply_ptrace_register (regcache *regcache, int regno,
83 const char *buf) override;
85 struct emit_ops *emit_ops () override;
87 int get_ipa_tdesc_idx () override;
89 protected:
91 void low_arch_setup () override;
93 bool low_cannot_fetch_register (int regno) override;
95 bool low_cannot_store_register (int regno) override;
97 bool low_supports_breakpoints () override;
99 CORE_ADDR low_get_pc (regcache *regcache) override;
101 void low_set_pc (regcache *regcache, CORE_ADDR newpc) override;
103 int low_decr_pc_after_break () override;
105 bool low_breakpoint_at (CORE_ADDR pc) override;
107 int low_get_thread_area (int lwpid, CORE_ADDR *addrp) override;
110 /* The singleton target ops object. */
112 static s390_target the_s390_target;
114 static int s390_regmap[] = {
115 PT_PSWMASK, PT_PSWADDR,
117 PT_GPR0, PT_GPR1, PT_GPR2, PT_GPR3,
118 PT_GPR4, PT_GPR5, PT_GPR6, PT_GPR7,
119 PT_GPR8, PT_GPR9, PT_GPR10, PT_GPR11,
120 PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15,
122 PT_ACR0, PT_ACR1, PT_ACR2, PT_ACR3,
123 PT_ACR4, PT_ACR5, PT_ACR6, PT_ACR7,
124 PT_ACR8, PT_ACR9, PT_ACR10, PT_ACR11,
125 PT_ACR12, PT_ACR13, PT_ACR14, PT_ACR15,
127 PT_FPC,
129 #ifndef __s390x__
130 PT_FPR0_HI, PT_FPR1_HI, PT_FPR2_HI, PT_FPR3_HI,
131 PT_FPR4_HI, PT_FPR5_HI, PT_FPR6_HI, PT_FPR7_HI,
132 PT_FPR8_HI, PT_FPR9_HI, PT_FPR10_HI, PT_FPR11_HI,
133 PT_FPR12_HI, PT_FPR13_HI, PT_FPR14_HI, PT_FPR15_HI,
134 #else
135 PT_FPR0, PT_FPR1, PT_FPR2, PT_FPR3,
136 PT_FPR4, PT_FPR5, PT_FPR6, PT_FPR7,
137 PT_FPR8, PT_FPR9, PT_FPR10, PT_FPR11,
138 PT_FPR12, PT_FPR13, PT_FPR14, PT_FPR15,
139 #endif
141 PT_ORIGGPR2,
144 #define s390_num_regs_3264 68
146 #ifdef __s390x__
147 static int s390_regmap_3264[] = {
148 PT_PSWMASK, PT_PSWADDR,
150 PT_GPR0, PT_GPR0, PT_GPR1, PT_GPR1,
151 PT_GPR2, PT_GPR2, PT_GPR3, PT_GPR3,
152 PT_GPR4, PT_GPR4, PT_GPR5, PT_GPR5,
153 PT_GPR6, PT_GPR6, PT_GPR7, PT_GPR7,
154 PT_GPR8, PT_GPR8, PT_GPR9, PT_GPR9,
155 PT_GPR10, PT_GPR10, PT_GPR11, PT_GPR11,
156 PT_GPR12, PT_GPR12, PT_GPR13, PT_GPR13,
157 PT_GPR14, PT_GPR14, PT_GPR15, PT_GPR15,
159 PT_ACR0, PT_ACR1, PT_ACR2, PT_ACR3,
160 PT_ACR4, PT_ACR5, PT_ACR6, PT_ACR7,
161 PT_ACR8, PT_ACR9, PT_ACR10, PT_ACR11,
162 PT_ACR12, PT_ACR13, PT_ACR14, PT_ACR15,
164 PT_FPC,
166 PT_FPR0, PT_FPR1, PT_FPR2, PT_FPR3,
167 PT_FPR4, PT_FPR5, PT_FPR6, PT_FPR7,
168 PT_FPR8, PT_FPR9, PT_FPR10, PT_FPR11,
169 PT_FPR12, PT_FPR13, PT_FPR14, PT_FPR15,
171 PT_ORIGGPR2,
173 #else
174 static int s390_regmap_3264[] = {
175 PT_PSWMASK, PT_PSWADDR,
177 -1, PT_GPR0, -1, PT_GPR1,
178 -1, PT_GPR2, -1, PT_GPR3,
179 -1, PT_GPR4, -1, PT_GPR5,
180 -1, PT_GPR6, -1, PT_GPR7,
181 -1, PT_GPR8, -1, PT_GPR9,
182 -1, PT_GPR10, -1, PT_GPR11,
183 -1, PT_GPR12, -1, PT_GPR13,
184 -1, PT_GPR14, -1, PT_GPR15,
186 PT_ACR0, PT_ACR1, PT_ACR2, PT_ACR3,
187 PT_ACR4, PT_ACR5, PT_ACR6, PT_ACR7,
188 PT_ACR8, PT_ACR9, PT_ACR10, PT_ACR11,
189 PT_ACR12, PT_ACR13, PT_ACR14, PT_ACR15,
191 PT_FPC,
193 PT_FPR0_HI, PT_FPR1_HI, PT_FPR2_HI, PT_FPR3_HI,
194 PT_FPR4_HI, PT_FPR5_HI, PT_FPR6_HI, PT_FPR7_HI,
195 PT_FPR8_HI, PT_FPR9_HI, PT_FPR10_HI, PT_FPR11_HI,
196 PT_FPR12_HI, PT_FPR13_HI, PT_FPR14_HI, PT_FPR15_HI,
198 PT_ORIGGPR2,
200 #endif
203 bool
204 s390_target::low_cannot_fetch_register (int regno)
206 return false;
209 bool
210 s390_target::low_cannot_store_register (int regno)
212 return false;
215 void
216 s390_target::low_collect_ptrace_register (regcache *regcache, int regno,
217 char *buf)
219 int size = register_size (regcache->tdesc, regno);
220 const struct regs_info *regs_info = get_regs_info ();
221 struct usrregs_info *usr = regs_info->usrregs;
222 int regaddr = usr->regmap[regno];
224 if (size < sizeof (long))
226 memset (buf, 0, sizeof (long));
228 if ((regno ^ 1) < usr->num_regs
229 && usr->regmap[regno ^ 1] == regaddr)
231 collect_register (regcache, regno & ~1, buf);
232 collect_register (regcache, (regno & ~1) + 1,
233 buf + sizeof (long) - size);
235 else if (regaddr == PT_PSWMASK)
237 /* Convert 4-byte PSW mask to 8 bytes by clearing bit 12 and copying
238 the basic addressing mode bit from the PSW address. */
239 gdb_byte *addr = (gdb_byte *) alloca (register_size (regcache->tdesc, regno ^ 1));
240 collect_register (regcache, regno, buf);
241 collect_register (regcache, regno ^ 1, addr);
242 buf[1] &= ~0x8;
243 buf[size] |= (addr[0] & 0x80);
245 else if (regaddr == PT_PSWADDR)
247 /* Convert 4-byte PSW address to 8 bytes by clearing the addressing
248 mode bit (which gets copied to the PSW mask instead). */
249 collect_register (regcache, regno, buf + sizeof (long) - size);
250 buf[sizeof (long) - size] &= ~0x80;
252 else if ((regaddr >= PT_GPR0 && regaddr <= PT_GPR15)
253 || regaddr == PT_ORIGGPR2)
254 collect_register (regcache, regno, buf + sizeof (long) - size);
255 else
256 collect_register (regcache, regno, buf);
258 else if (regaddr != -1)
259 collect_register (regcache, regno, buf);
262 void
263 s390_target::low_supply_ptrace_register (regcache *regcache, int regno,
264 const char *buf)
266 int size = register_size (regcache->tdesc, regno);
267 const struct regs_info *regs_info = get_regs_info ();
268 struct usrregs_info *usr = regs_info->usrregs;
269 int regaddr = usr->regmap[regno];
271 if (size < sizeof (long))
273 if ((regno ^ 1) < usr->num_regs
274 && usr->regmap[regno ^ 1] == regaddr)
276 supply_register (regcache, regno & ~1, buf);
277 supply_register (regcache, (regno & ~1) + 1,
278 buf + sizeof (long) - size);
280 else if (regaddr == PT_PSWMASK)
282 /* Convert 8-byte PSW mask to 4 bytes by setting bit 12 and copying
283 the basic addressing mode into the PSW address. */
284 gdb_byte *mask = (gdb_byte *) alloca (size);
285 gdb_byte *addr = (gdb_byte *) alloca (register_size (regcache->tdesc, regno ^ 1));
286 memcpy (mask, buf, size);
287 mask[1] |= 0x8;
288 supply_register (regcache, regno, mask);
290 collect_register (regcache, regno ^ 1, addr);
291 addr[0] &= ~0x80;
292 addr[0] |= (buf[size] & 0x80);
293 supply_register (regcache, regno ^ 1, addr);
295 else if (regaddr == PT_PSWADDR)
297 /* Convert 8-byte PSW address to 4 bytes by truncating, but
298 keeping the addressing mode bit (which was set from the mask). */
299 gdb_byte *addr = (gdb_byte *) alloca (size);
300 char amode;
301 collect_register (regcache, regno, addr);
302 amode = addr[0] & 0x80;
303 memcpy (addr, buf + sizeof (long) - size, size);
304 addr[0] &= ~0x80;
305 addr[0] |= amode;
306 supply_register (regcache, regno, addr);
308 else if ((regaddr >= PT_GPR0 && regaddr <= PT_GPR15)
309 || regaddr == PT_ORIGGPR2)
310 supply_register (regcache, regno, buf + sizeof (long) - size);
311 else
312 supply_register (regcache, regno, buf);
314 else if (regaddr != -1)
315 supply_register (regcache, regno, buf);
318 /* Provide only a fill function for the general register set. ps_lgetregs
319 will use this for NPTL support. */
321 static void
322 s390_fill_gregset (struct regcache *regcache, void *buf)
324 int i;
325 const struct regs_info *regs_info = the_linux_target->get_regs_info ();
326 struct usrregs_info *usr = regs_info->usrregs;
328 for (i = 0; i < usr->num_regs; i++)
330 if (usr->regmap[i] < PT_PSWMASK
331 || usr->regmap[i] > PT_ACR15)
332 continue;
334 ((s390_target *) the_linux_target)->low_collect_ptrace_register
335 (regcache, i, (char *) buf + usr->regmap[i]);
339 /* Fill and store functions for extended register sets. */
341 #ifndef __s390x__
342 static void
343 s390_fill_gprs_high (struct regcache *regcache, void *buf)
345 int r0h = find_regno (regcache->tdesc, "r0h");
346 int i;
348 for (i = 0; i < 16; i++)
349 collect_register (regcache, r0h + 2 * i, (char *) buf + 4 * i);
352 static void
353 s390_store_gprs_high (struct regcache *regcache, const void *buf)
355 int r0h = find_regno (regcache->tdesc, "r0h");
356 int i;
358 for (i = 0; i < 16; i++)
359 supply_register (regcache, r0h + 2 * i, (const char *) buf + 4 * i);
361 #endif
363 static void
364 s390_store_last_break (struct regcache *regcache, const void *buf)
366 const char *p;
368 p = (const char *) buf + 8 - register_size (regcache->tdesc, 0);
369 supply_register_by_name (regcache, "last_break", p);
372 static void
373 s390_fill_system_call (struct regcache *regcache, void *buf)
375 collect_register_by_name (regcache, "system_call", buf);
378 static void
379 s390_store_system_call (struct regcache *regcache, const void *buf)
381 supply_register_by_name (regcache, "system_call", buf);
384 static void
385 s390_store_tdb (struct regcache *regcache, const void *buf)
387 int tdb0 = find_regno (regcache->tdesc, "tdb0");
388 int tr0 = find_regno (regcache->tdesc, "tr0");
389 int i;
391 for (i = 0; i < 4; i++)
392 supply_register (regcache, tdb0 + i, (const char *) buf + 8 * i);
394 for (i = 0; i < 16; i++)
395 supply_register (regcache, tr0 + i, (const char *) buf + 8 * (16 + i));
398 static void
399 s390_fill_vxrs_low (struct regcache *regcache, void *buf)
401 int v0 = find_regno (regcache->tdesc, "v0l");
402 int i;
404 for (i = 0; i < 16; i++)
405 collect_register (regcache, v0 + i, (char *) buf + 8 * i);
408 static void
409 s390_store_vxrs_low (struct regcache *regcache, const void *buf)
411 int v0 = find_regno (regcache->tdesc, "v0l");
412 int i;
414 for (i = 0; i < 16; i++)
415 supply_register (regcache, v0 + i, (const char *) buf + 8 * i);
418 static void
419 s390_fill_vxrs_high (struct regcache *regcache, void *buf)
421 int v16 = find_regno (regcache->tdesc, "v16");
422 int i;
424 for (i = 0; i < 16; i++)
425 collect_register (regcache, v16 + i, (char *) buf + 16 * i);
428 static void
429 s390_store_vxrs_high (struct regcache *regcache, const void *buf)
431 int v16 = find_regno (regcache->tdesc, "v16");
432 int i;
434 for (i = 0; i < 16; i++)
435 supply_register (regcache, v16 + i, (const char *) buf + 16 * i);
438 static void
439 s390_store_gs (struct regcache *regcache, const void *buf)
441 int gsd = find_regno (regcache->tdesc, "gsd");
442 int i;
444 for (i = 0; i < 3; i++)
445 supply_register (regcache, gsd + i, (const char *) buf + 8 * (i + 1));
448 static void
449 s390_store_gsbc (struct regcache *regcache, const void *buf)
451 int bc_gsd = find_regno (regcache->tdesc, "bc_gsd");
452 int i;
454 for (i = 0; i < 3; i++)
455 supply_register (regcache, bc_gsd + i, (const char *) buf + 8 * (i + 1));
458 static struct regset_info s390_regsets[] = {
459 { 0, 0, 0, 0, GENERAL_REGS, s390_fill_gregset, NULL },
460 #ifndef __s390x__
461 { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_S390_HIGH_GPRS, 0,
462 EXTENDED_REGS, s390_fill_gprs_high, s390_store_gprs_high },
463 #endif
464 /* Last break address is read-only; no fill function. */
465 { PTRACE_GETREGSET, -1, NT_S390_LAST_BREAK, 0, EXTENDED_REGS,
466 NULL, s390_store_last_break },
467 { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_S390_SYSTEM_CALL, 0,
468 EXTENDED_REGS, s390_fill_system_call, s390_store_system_call },
469 /* TDB is read-only. */
470 { PTRACE_GETREGSET, -1, NT_S390_TDB, 0, EXTENDED_REGS,
471 NULL, s390_store_tdb },
472 { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_S390_VXRS_LOW, 0,
473 EXTENDED_REGS, s390_fill_vxrs_low, s390_store_vxrs_low },
474 { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_S390_VXRS_HIGH, 0,
475 EXTENDED_REGS, s390_fill_vxrs_high, s390_store_vxrs_high },
476 /* Guarded storage registers are read-only. */
477 { PTRACE_GETREGSET, -1, NT_S390_GS_CB, 0, EXTENDED_REGS,
478 NULL, s390_store_gs },
479 { PTRACE_GETREGSET, -1, NT_S390_GS_BC, 0, EXTENDED_REGS,
480 NULL, s390_store_gsbc },
481 NULL_REGSET
485 static const gdb_byte s390_breakpoint[] = { 0, 1 };
486 #define s390_breakpoint_len 2
488 /* Implementation of target ops method "sw_breakpoint_from_kind". */
490 const gdb_byte *
491 s390_target::sw_breakpoint_from_kind (int kind, int *size)
493 *size = s390_breakpoint_len;
494 return s390_breakpoint;
497 bool
498 s390_target::low_supports_breakpoints ()
500 return true;
503 CORE_ADDR
504 s390_target::low_get_pc (regcache *regcache)
506 if (register_size (regcache->tdesc, 0) == 4)
508 unsigned int pswa;
509 collect_register_by_name (regcache, "pswa", &pswa);
510 return pswa & 0x7fffffff;
512 else
514 unsigned long pc;
515 collect_register_by_name (regcache, "pswa", &pc);
516 return pc;
520 void
521 s390_target::low_set_pc (regcache *regcache, CORE_ADDR newpc)
523 if (register_size (regcache->tdesc, 0) == 4)
525 unsigned int pswa;
526 collect_register_by_name (regcache, "pswa", &pswa);
527 pswa = (pswa & 0x80000000) | (newpc & 0x7fffffff);
528 supply_register_by_name (regcache, "pswa", &pswa);
530 else
532 unsigned long pc = newpc;
533 supply_register_by_name (regcache, "pswa", &pc);
538 s390_target::low_decr_pc_after_break ()
540 return s390_breakpoint_len;
543 /* Determine the word size for the given PID, in bytes. */
545 #ifdef __s390x__
546 static int
547 s390_get_wordsize (int pid)
549 errno = 0;
550 PTRACE_XFER_TYPE pswm = ptrace (PTRACE_PEEKUSER, pid,
551 (PTRACE_TYPE_ARG3) 0,
552 (PTRACE_TYPE_ARG4) 0);
553 if (errno != 0)
555 warning (_("Couldn't determine word size, assuming 64-bit."));
556 return 8;
558 /* Derive word size from extended addressing mode (PSW bit 31). */
559 return pswm & (1L << 32) ? 8 : 4;
561 #else
562 #define s390_get_wordsize(pid) 4
563 #endif
565 static int
566 s390_check_regset (int pid, int regset, int regsize)
568 void *buf = alloca (regsize);
569 struct iovec iov;
571 iov.iov_base = buf;
572 iov.iov_len = regsize;
574 if (ptrace (PTRACE_GETREGSET, pid, (long) regset, (long) &iov) >= 0
575 || errno == ENODATA)
576 return 1;
577 return 0;
580 /* For a 31-bit inferior, whether the kernel supports using the full
581 64-bit GPRs. */
582 static int have_hwcap_s390_high_gprs = 0;
583 static int have_hwcap_s390_vx = 0;
585 void
586 s390_target::low_arch_setup ()
588 const struct target_desc *tdesc;
589 struct regset_info *regset;
591 /* Determine word size and HWCAP. */
592 int pid = pid_of (current_thread);
593 int wordsize = s390_get_wordsize (pid);
594 unsigned long hwcap = linux_get_hwcap (pid, wordsize);
596 /* Check whether the kernel supports extra register sets. */
597 int have_regset_last_break
598 = s390_check_regset (pid, NT_S390_LAST_BREAK, 8);
599 int have_regset_system_call
600 = s390_check_regset (pid, NT_S390_SYSTEM_CALL, 4);
601 int have_regset_tdb
602 = (s390_check_regset (pid, NT_S390_TDB, 256)
603 && (hwcap & HWCAP_S390_TE) != 0);
604 int have_regset_vxrs
605 = (s390_check_regset (pid, NT_S390_VXRS_LOW, 128)
606 && s390_check_regset (pid, NT_S390_VXRS_HIGH, 256)
607 && (hwcap & HWCAP_S390_VX) != 0);
608 int have_regset_gs
609 = (s390_check_regset (pid, NT_S390_GS_CB, 32)
610 && s390_check_regset (pid, NT_S390_GS_BC, 32)
611 && (hwcap & HWCAP_S390_GS) != 0);
614 #ifdef __s390x__
615 if (wordsize == 8)
617 if (have_regset_gs)
618 tdesc = tdesc_s390x_gs_linux64;
619 else if (have_regset_vxrs)
620 tdesc = (have_regset_tdb ? tdesc_s390x_tevx_linux64 :
621 tdesc_s390x_vx_linux64);
622 else if (have_regset_tdb)
623 tdesc = tdesc_s390x_te_linux64;
624 else if (have_regset_system_call)
625 tdesc = tdesc_s390x_linux64v2;
626 else if (have_regset_last_break)
627 tdesc = tdesc_s390x_linux64v1;
628 else
629 tdesc = tdesc_s390x_linux64;
632 /* For a 31-bit inferior, check whether the kernel supports
633 using the full 64-bit GPRs. */
634 else
635 #endif
636 if (hwcap & HWCAP_S390_HIGH_GPRS)
638 have_hwcap_s390_high_gprs = 1;
639 if (have_regset_gs)
640 tdesc = tdesc_s390_gs_linux64;
641 else if (have_regset_vxrs)
642 tdesc = (have_regset_tdb ? tdesc_s390_tevx_linux64 :
643 tdesc_s390_vx_linux64);
644 else if (have_regset_tdb)
645 tdesc = tdesc_s390_te_linux64;
646 else if (have_regset_system_call)
647 tdesc = tdesc_s390_linux64v2;
648 else if (have_regset_last_break)
649 tdesc = tdesc_s390_linux64v1;
650 else
651 tdesc = tdesc_s390_linux64;
653 else
655 /* Assume 31-bit inferior process. */
656 if (have_regset_system_call)
657 tdesc = tdesc_s390_linux32v2;
658 else if (have_regset_last_break)
659 tdesc = tdesc_s390_linux32v1;
660 else
661 tdesc = tdesc_s390_linux32;
664 have_hwcap_s390_vx = have_regset_vxrs;
667 /* Update target_regsets according to available register sets. */
668 for (regset = s390_regsets; regset->size >= 0; regset++)
669 if (regset->get_request == PTRACE_GETREGSET)
670 switch (regset->nt_type)
672 #ifndef __s390x__
673 case NT_S390_HIGH_GPRS:
674 regset->size = have_hwcap_s390_high_gprs ? 64 : 0;
675 break;
676 #endif
677 case NT_S390_LAST_BREAK:
678 regset->size = have_regset_last_break ? 8 : 0;
679 break;
680 case NT_S390_SYSTEM_CALL:
681 regset->size = have_regset_system_call ? 4 : 0;
682 break;
683 case NT_S390_TDB:
684 regset->size = have_regset_tdb ? 256 : 0;
685 break;
686 case NT_S390_VXRS_LOW:
687 regset->size = have_regset_vxrs ? 128 : 0;
688 break;
689 case NT_S390_VXRS_HIGH:
690 regset->size = have_regset_vxrs ? 256 : 0;
691 break;
692 case NT_S390_GS_CB:
693 case NT_S390_GS_BC:
694 regset->size = have_regset_gs ? 32 : 0;
695 default:
696 break;
699 current_process ()->tdesc = tdesc;
703 bool
704 s390_target::low_breakpoint_at (CORE_ADDR pc)
706 unsigned char c[s390_breakpoint_len];
707 read_inferior_memory (pc, c, s390_breakpoint_len);
708 return memcmp (c, s390_breakpoint, s390_breakpoint_len) == 0;
711 /* Breakpoint/Watchpoint support. */
713 /* The "supports_z_point_type" target ops method. */
715 bool
716 s390_target::supports_z_point_type (char z_type)
718 switch (z_type)
720 case Z_PACKET_SW_BP:
721 return true;
722 default:
723 return false;
727 static struct usrregs_info s390_usrregs_info =
729 s390_num_regs,
730 s390_regmap,
733 static struct regsets_info s390_regsets_info =
735 s390_regsets, /* regsets */
736 0, /* num_regsets */
737 NULL, /* disabled_regsets */
740 static struct regs_info myregs_info =
742 NULL, /* regset_bitmap */
743 &s390_usrregs_info,
744 &s390_regsets_info
747 static struct usrregs_info s390_usrregs_info_3264 =
749 s390_num_regs_3264,
750 s390_regmap_3264
753 static struct regsets_info s390_regsets_info_3264 =
755 s390_regsets, /* regsets */
756 0, /* num_regsets */
757 NULL, /* disabled_regsets */
760 static struct regs_info regs_info_3264 =
762 NULL, /* regset_bitmap */
763 &s390_usrregs_info_3264,
764 &s390_regsets_info_3264
767 const regs_info *
768 s390_target::get_regs_info ()
770 if (have_hwcap_s390_high_gprs)
772 #ifdef __s390x__
773 const struct target_desc *tdesc = current_process ()->tdesc;
775 if (register_size (tdesc, 0) == 4)
776 return &regs_info_3264;
777 #else
778 return &regs_info_3264;
779 #endif
781 return &myregs_info;
784 /* The "supports_tracepoints" target ops method. */
786 bool
787 s390_target::supports_tracepoints ()
789 return true;
792 /* Implementation of linux target ops method "low_get_thread_area". */
795 s390_target::low_get_thread_area (int lwpid, CORE_ADDR *addrp)
797 CORE_ADDR res = ptrace (PTRACE_PEEKUSER, lwpid, (long) PT_ACR0, (long) 0);
798 #ifdef __s390x__
799 struct regcache *regcache = get_thread_regcache (current_thread, 0);
801 if (register_size (regcache->tdesc, 0) == 4)
802 res &= 0xffffffffull;
803 #endif
804 *addrp = res;
805 return 0;
809 /* Fast tracepoint support.
811 The register save area on stack is identical for all targets:
813 0x000+i*0x10: VR0-VR31
814 0x200+i*8: GR0-GR15
815 0x280+i*4: AR0-AR15
816 0x2c0: PSWM [64-bit]
817 0x2c8: PSWA [64-bit]
818 0x2d0: FPC
820 If we're on 31-bit linux, we just don't store the high parts of the GPRs.
821 Likewise, if there's no VX support, we just store the FRs into the slots
822 of low VR halves. The agent code is responsible for rearranging that
823 into regcache. */
825 /* Code sequence saving GPRs for 31-bit target with no high GPRs. There's
826 one trick used at the very beginning: since there's no way to allocate
827 stack space without destroying CC (lay instruction can do it, but it's
828 only supported on later CPUs), we take 4 different execution paths for
829 every possible value of CC, allocate stack space, save %r0, stuff the
830 CC value in %r0 (shifted to match its position in PSWM high word),
831 then branch to common path. */
833 static const unsigned char s390_ft_entry_gpr_esa[] = {
834 0xa7, 0x14, 0x00, 0x1e, /* jo .Lcc3 */
835 0xa7, 0x24, 0x00, 0x14, /* jh .Lcc2 */
836 0xa7, 0x44, 0x00, 0x0a, /* jl .Lcc1 */
837 /* CC = 0 */
838 0xa7, 0xfa, 0xfd, 0x00, /* ahi %r15, -0x300 */
839 0x50, 0x00, 0xf2, 0x04, /* st %r0, 0x204(%r15) */
840 0xa7, 0x08, 0x00, 0x00, /* lhi %r0, 0 */
841 0xa7, 0xf4, 0x00, 0x18, /* j .Lccdone */
842 /* .Lcc1: */
843 0xa7, 0xfa, 0xfd, 0x00, /* ahi %r15, -0x300 */
844 0x50, 0x00, 0xf2, 0x04, /* st %r0, 0x204(%r15) */
845 0xa7, 0x08, 0x10, 0x00, /* lhi %r0, 0x1000 */
846 0xa7, 0xf4, 0x00, 0x10, /* j .Lccdone */
847 /* .Lcc2: */
848 0xa7, 0xfa, 0xfd, 0x00, /* ahi %r15, -0x300 */
849 0x50, 0x00, 0xf2, 0x04, /* st %r0, 0x204(%r15) */
850 0xa7, 0x08, 0x20, 0x00, /* lhi %r0, 0x2000 */
851 0xa7, 0xf4, 0x00, 0x08, /* j .Lccdone */
852 /* .Lcc3: */
853 0xa7, 0xfa, 0xfd, 0x00, /* ahi %r15, -0x300 */
854 0x50, 0x00, 0xf2, 0x04, /* st %r0, 0x204(%r15) */
855 0xa7, 0x08, 0x30, 0x00, /* lhi %r0, 0x3000 */
856 /* .Lccdone: */
857 0x50, 0x10, 0xf2, 0x0c, /* st %r1, 0x20c(%r15) */
858 0x50, 0x20, 0xf2, 0x14, /* st %r2, 0x214(%r15) */
859 0x50, 0x30, 0xf2, 0x1c, /* st %r3, 0x21c(%r15) */
860 0x50, 0x40, 0xf2, 0x24, /* st %r4, 0x224(%r15) */
861 0x50, 0x50, 0xf2, 0x2c, /* st %r5, 0x22c(%r15) */
862 0x50, 0x60, 0xf2, 0x34, /* st %r6, 0x234(%r15) */
863 0x50, 0x70, 0xf2, 0x3c, /* st %r7, 0x23c(%r15) */
864 0x50, 0x80, 0xf2, 0x44, /* st %r8, 0x244(%r15) */
865 0x50, 0x90, 0xf2, 0x4c, /* st %r9, 0x24c(%r15) */
866 0x50, 0xa0, 0xf2, 0x54, /* st %r10, 0x254(%r15) */
867 0x50, 0xb0, 0xf2, 0x5c, /* st %r11, 0x25c(%r15) */
868 0x50, 0xc0, 0xf2, 0x64, /* st %r12, 0x264(%r15) */
869 0x50, 0xd0, 0xf2, 0x6c, /* st %r13, 0x26c(%r15) */
870 0x50, 0xe0, 0xf2, 0x74, /* st %r14, 0x274(%r15) */
871 /* Compute original value of %r15 and store it. We use ahi instead
872 of la to preserve the whole value, and not just the low 31 bits.
873 This is not particularly important here, but essential in the
874 zarch case where someone might be using the high word of %r15
875 as an extra register. */
876 0x18, 0x1f, /* lr %r1, %r15 */
877 0xa7, 0x1a, 0x03, 0x00, /* ahi %r1, 0x300 */
878 0x50, 0x10, 0xf2, 0x7c, /* st %r1, 0x27c(%r15) */
881 /* Code sequence saving GPRs for 31-bit target with high GPRs and for 64-bit
882 target. Same as above, except this time we can use load/store multiple,
883 since the 64-bit regs are tightly packed. */
885 static const unsigned char s390_ft_entry_gpr_zarch[] = {
886 0xa7, 0x14, 0x00, 0x21, /* jo .Lcc3 */
887 0xa7, 0x24, 0x00, 0x16, /* jh .Lcc2 */
888 0xa7, 0x44, 0x00, 0x0b, /* jl .Lcc1 */
889 /* CC = 0 */
890 0xa7, 0xfb, 0xfd, 0x00, /* aghi %r15, -0x300 */
891 0xeb, 0x0e, 0xf2, 0x00, 0x00, 0x24, /* stmg %r0, %r14, 0x200(%r15) */
892 0xa7, 0x08, 0x00, 0x00, /* lhi %r0, 0 */
893 0xa7, 0xf4, 0x00, 0x1b, /* j .Lccdone */
894 /* .Lcc1: */
895 0xa7, 0xfb, 0xfd, 0x00, /* aghi %r15, -0x300 */
896 0xeb, 0x0e, 0xf2, 0x00, 0x00, 0x24, /* stmg %r0, %r14, 0x200(%r15) */
897 0xa7, 0x08, 0x10, 0x00, /* lhi %r0, 0x1000 */
898 0xa7, 0xf4, 0x00, 0x12, /* j .Lccdone */
899 /* .Lcc2: */
900 0xa7, 0xfb, 0xfd, 0x00, /* aghi %r15, -0x300 */
901 0xeb, 0x0e, 0xf2, 0x00, 0x00, 0x24, /* stmg %r0, %r14, 0x200(%r15) */
902 0xa7, 0x08, 0x20, 0x00, /* lhi %r0, 0x2000 */
903 0xa7, 0xf4, 0x00, 0x09, /* j .Lccdone */
904 /* .Lcc3: */
905 0xa7, 0xfb, 0xfd, 0x00, /* aghi %r15, -0x300 */
906 0xeb, 0x0e, 0xf2, 0x00, 0x00, 0x24, /* stmg %r0, %r14, 0x200(%r15) */
907 0xa7, 0x08, 0x30, 0x00, /* lhi %r0, 0x3000 */
908 /* .Lccdone: */
909 0xb9, 0x04, 0x00, 0x1f, /* lgr %r1, %r15 */
910 0xa7, 0x1b, 0x03, 0x00, /* aghi %r1, 0x300 */
911 0xe3, 0x10, 0xf2, 0x78, 0x00, 0x24, /* stg %r1, 0x278(%r15) */
914 /* Code sequence saving ARs, PSWM and FPC. PSWM has to be assembled from
915 current PSWM (read by epsw) and CC from entry (in %r0). */
917 static const unsigned char s390_ft_entry_misc[] = {
918 0x9b, 0x0f, 0xf2, 0x80, /* stam %a0, %a15, 0x20(%%r15) */
919 0xb9, 0x8d, 0x00, 0x23, /* epsw %r2, %r3 */
920 0xa7, 0x18, 0xcf, 0xff, /* lhi %r1, ~0x3000 */
921 0x14, 0x21, /* nr %r2, %r1 */
922 0x16, 0x20, /* or %r2, %r0 */
923 0x50, 0x20, 0xf2, 0xc0, /* st %r2, 0x2c0(%r15) */
924 0x50, 0x30, 0xf2, 0xc4, /* st %r3, 0x2c4(%r15) */
925 0xb2, 0x9c, 0xf2, 0xd0, /* stfpc 0x2d0(%r15) */
928 /* Code sequence saving FRs, used if VX not supported. */
930 static const unsigned char s390_ft_entry_fr[] = {
931 0x60, 0x00, 0xf0, 0x00, /* std %f0, 0x000(%r15) */
932 0x60, 0x10, 0xf0, 0x10, /* std %f1, 0x010(%r15) */
933 0x60, 0x20, 0xf0, 0x20, /* std %f2, 0x020(%r15) */
934 0x60, 0x30, 0xf0, 0x30, /* std %f3, 0x030(%r15) */
935 0x60, 0x40, 0xf0, 0x40, /* std %f4, 0x040(%r15) */
936 0x60, 0x50, 0xf0, 0x50, /* std %f5, 0x050(%r15) */
937 0x60, 0x60, 0xf0, 0x60, /* std %f6, 0x060(%r15) */
938 0x60, 0x70, 0xf0, 0x70, /* std %f7, 0x070(%r15) */
939 0x60, 0x80, 0xf0, 0x80, /* std %f8, 0x080(%r15) */
940 0x60, 0x90, 0xf0, 0x90, /* std %f9, 0x090(%r15) */
941 0x60, 0xa0, 0xf0, 0xa0, /* std %f10, 0x0a0(%r15) */
942 0x60, 0xb0, 0xf0, 0xb0, /* std %f11, 0x0b0(%r15) */
943 0x60, 0xc0, 0xf0, 0xc0, /* std %f12, 0x0c0(%r15) */
944 0x60, 0xd0, 0xf0, 0xd0, /* std %f13, 0x0d0(%r15) */
945 0x60, 0xe0, 0xf0, 0xe0, /* std %f14, 0x0e0(%r15) */
946 0x60, 0xf0, 0xf0, 0xf0, /* std %f15, 0x0f0(%r15) */
949 /* Code sequence saving VRs, used if VX not supported. */
951 static const unsigned char s390_ft_entry_vr[] = {
952 0xe7, 0x0f, 0xf0, 0x00, 0x00, 0x3e, /* vstm %v0, %v15, 0x000(%r15) */
953 0xe7, 0x0f, 0xf1, 0x00, 0x0c, 0x3e, /* vstm %v16, %v31, 0x100(%r15) */
956 /* Code sequence doing the collection call for 31-bit target. %r1 contains
957 the address of the literal pool. */
959 static const unsigned char s390_ft_main_31[] = {
960 /* Load the literals into registers. */
961 0x58, 0x50, 0x10, 0x00, /* l %r5, 0x0(%r1) */
962 0x58, 0x20, 0x10, 0x04, /* l %r2, 0x4(%r1) */
963 0x58, 0x40, 0x10, 0x08, /* l %r4, 0x8(%r1) */
964 0x58, 0x60, 0x10, 0x0c, /* l %r6, 0xc(%r1) */
965 /* Save original PSWA (tracepoint address | 0x80000000). */
966 0x50, 0x50, 0xf2, 0xcc, /* st %r5, 0x2cc(%r15) */
967 /* Construct a collecting_t object at %r15+0x2e0. */
968 0x50, 0x20, 0xf2, 0xe0, /* st %r2, 0x2e0(%r15) */
969 0x9b, 0x00, 0xf2, 0xe4, /* stam %a0, %a0, 0x2e4(%r15) */
970 /* Move its address to %r0. */
971 0x41, 0x00, 0xf2, 0xe0, /* la %r0, 0x2e0(%r15) */
972 /* Take the lock. */
973 /* .Lloop: */
974 0xa7, 0x18, 0x00, 0x00, /* lhi %r1, 0 */
975 0xba, 0x10, 0x60, 0x00, /* cs %r1, %r0, 0(%r6) */
976 0xa7, 0x74, 0xff, 0xfc, /* jne .Lloop */
977 /* Address of the register save block to %r3. */
978 0x18, 0x3f, /* lr %r3, %r15 */
979 /* Make a stack frame, so that we can call the collector. */
980 0xa7, 0xfa, 0xff, 0xa0, /* ahi %r15, -0x60 */
981 /* Call it. */
982 0x0d, 0xe4, /* basr %r14, %r4 */
983 /* And get rid of the stack frame again. */
984 0x41, 0xf0, 0xf0, 0x60, /* la %r15, 0x60(%r15) */
985 /* Leave the lock. */
986 0x07, 0xf0, /* br %r0 */
987 0xa7, 0x18, 0x00, 0x00, /* lhi %r1, 0 */
988 0x50, 0x10, 0x60, 0x00, /* st %t1, 0(%r6) */
991 /* Code sequence doing the collection call for 64-bit target. %r1 contains
992 the address of the literal pool. */
994 static const unsigned char s390_ft_main_64[] = {
995 /* Load the literals into registers. */
996 0xe3, 0x50, 0x10, 0x00, 0x00, 0x04, /* lg %r5, 0x00(%r1) */
997 0xe3, 0x20, 0x10, 0x08, 0x00, 0x04, /* lg %r2, 0x08(%r1) */
998 0xe3, 0x40, 0x10, 0x10, 0x00, 0x04, /* lg %r4, 0x10(%r1) */
999 0xe3, 0x60, 0x10, 0x18, 0x00, 0x04, /* lg %r6, 0x18(%r1) */
1000 /* Save original PSWA (tracepoint address). */
1001 0xe3, 0x50, 0xf2, 0xc8, 0x00, 0x24, /* stg %r5, 0x2c8(%r15) */
1002 /* Construct a collecting_t object at %r15+0x2e0. */
1003 0xe3, 0x20, 0xf2, 0xe0, 0x00, 0x24, /* stg %r2, 0x2e0(%r15) */
1004 0x9b, 0x01, 0xf2, 0xe8, /* stam %a0, %a1, 0x2e8(%r15) */
1005 /* Move its address to %r0. */
1006 0x41, 0x00, 0xf2, 0xe0, /* la %r0, 0x2e0(%r15) */
1007 /* Take the lock. */
1008 /* .Lloop: */
1009 0xa7, 0x19, 0x00, 0x00, /* lghi %r1, 0 */
1010 0xeb, 0x10, 0x60, 0x00, 0x00, 0x30, /* csg %r1, %r0, 0(%r6) */
1011 0xa7, 0x74, 0xff, 0xfb, /* jne .Lloop */
1012 /* Address of the register save block to %r3. */
1013 0xb9, 0x04, 0x00, 0x3f, /* lgr %r3, %r15 */
1014 /* Make a stack frame, so that we can call the collector. */
1015 0xa7, 0xfb, 0xff, 0x60, /* aghi %r15, -0xa0 */
1016 /* Call it. */
1017 0x0d, 0xe4, /* basr %r14, %r4 */
1018 /* And get rid of the stack frame again. */
1019 0x41, 0xf0, 0xf0, 0xa0, /* la %r15, 0xa0(%r15) */
1020 /* Leave the lock. */
1021 0x07, 0xf0, /* br %r0 */
1022 0xa7, 0x19, 0x00, 0x00, /* lghi %r1, 0 */
1023 0xe3, 0x10, 0x60, 0x00, 0x00, 0x24, /* stg %t1, 0(%r6) */
1026 /* Code sequence restoring FRs, for targets with no VX support. */
1028 static const unsigned char s390_ft_exit_fr[] = {
1029 0x68, 0x00, 0xf0, 0x00, /* ld %f0, 0x000(%r15) */
1030 0x68, 0x10, 0xf0, 0x10, /* ld %f1, 0x010(%r15) */
1031 0x68, 0x20, 0xf0, 0x20, /* ld %f2, 0x020(%r15) */
1032 0x68, 0x30, 0xf0, 0x30, /* ld %f3, 0x030(%r15) */
1033 0x68, 0x40, 0xf0, 0x40, /* ld %f4, 0x040(%r15) */
1034 0x68, 0x50, 0xf0, 0x50, /* ld %f5, 0x050(%r15) */
1035 0x68, 0x60, 0xf0, 0x60, /* ld %f6, 0x060(%r15) */
1036 0x68, 0x70, 0xf0, 0x70, /* ld %f7, 0x070(%r15) */
1037 0x68, 0x80, 0xf0, 0x80, /* ld %f8, 0x080(%r15) */
1038 0x68, 0x90, 0xf0, 0x90, /* ld %f9, 0x090(%r15) */
1039 0x68, 0xa0, 0xf0, 0xa0, /* ld %f10, 0x0a0(%r15) */
1040 0x68, 0xb0, 0xf0, 0xb0, /* ld %f11, 0x0b0(%r15) */
1041 0x68, 0xc0, 0xf0, 0xc0, /* ld %f12, 0x0c0(%r15) */
1042 0x68, 0xd0, 0xf0, 0xd0, /* ld %f13, 0x0d0(%r15) */
1043 0x68, 0xe0, 0xf0, 0xe0, /* ld %f14, 0x0e0(%r15) */
1044 0x68, 0xf0, 0xf0, 0xf0, /* ld %f15, 0x0f0(%r15) */
1047 /* Code sequence restoring VRs. */
1049 static const unsigned char s390_ft_exit_vr[] = {
1050 0xe7, 0x0f, 0xf0, 0x00, 0x00, 0x36, /* vlm %v0, %v15, 0x000(%r15) */
1051 0xe7, 0x0f, 0xf1, 0x00, 0x0c, 0x36, /* vlm %v16, %v31, 0x100(%r15) */
1054 /* Code sequence restoring misc registers. As for PSWM, only CC should be
1055 modified by C code, so we use the alr instruction to restore it by
1056 manufacturing an operand that'll result in the original flags. */
1058 static const unsigned char s390_ft_exit_misc[] = {
1059 0xb2, 0x9d, 0xf2, 0xd0, /* lfpc 0x2d0(%r15) */
1060 0x58, 0x00, 0xf2, 0xc0, /* l %r0, 0x2c0(%r15) */
1061 /* Extract CC to high 2 bits of %r0. */
1062 0x88, 0x00, 0x00, 0x0c, /* srl %r0, 12 */
1063 0x89, 0x00, 0x00, 0x1e, /* sll %r0, 30 */
1064 /* Add %r0 to itself. Result will be nonzero iff CC bit 0 is set, and
1065 will have carry iff CC bit 1 is set - resulting in the same flags
1066 as the original. */
1067 0x1e, 0x00, /* alr %r0, %r0 */
1068 0x9a, 0x0f, 0xf2, 0x80, /* lam %a0, %a15, 0x280(%r15) */
1071 /* Code sequence restoring GPRs, for 31-bit targets with no high GPRs. */
1073 static const unsigned char s390_ft_exit_gpr_esa[] = {
1074 0x58, 0x00, 0xf2, 0x04, /* l %r0, 0x204(%r15) */
1075 0x58, 0x10, 0xf2, 0x0c, /* l %r1, 0x20c(%r15) */
1076 0x58, 0x20, 0xf2, 0x14, /* l %r2, 0x214(%r15) */
1077 0x58, 0x30, 0xf2, 0x1c, /* l %r3, 0x21c(%r15) */
1078 0x58, 0x40, 0xf2, 0x24, /* l %r4, 0x224(%r15) */
1079 0x58, 0x50, 0xf2, 0x2c, /* l %r5, 0x22c(%r15) */
1080 0x58, 0x60, 0xf2, 0x34, /* l %r6, 0x234(%r15) */
1081 0x58, 0x70, 0xf2, 0x3c, /* l %r7, 0x23c(%r15) */
1082 0x58, 0x80, 0xf2, 0x44, /* l %r8, 0x244(%r15) */
1083 0x58, 0x90, 0xf2, 0x4c, /* l %r9, 0x24c(%r15) */
1084 0x58, 0xa0, 0xf2, 0x54, /* l %r10, 0x254(%r15) */
1085 0x58, 0xb0, 0xf2, 0x5c, /* l %r11, 0x25c(%r15) */
1086 0x58, 0xc0, 0xf2, 0x64, /* l %r12, 0x264(%r15) */
1087 0x58, 0xd0, 0xf2, 0x6c, /* l %r13, 0x26c(%r15) */
1088 0x58, 0xe0, 0xf2, 0x74, /* l %r14, 0x274(%r15) */
1089 0x58, 0xf0, 0xf2, 0x7c, /* l %r15, 0x27c(%r15) */
1092 /* Code sequence restoring GPRs, for 64-bit targets and 31-bit targets
1093 with high GPRs. */
1095 static const unsigned char s390_ft_exit_gpr_zarch[] = {
1096 0xeb, 0x0f, 0xf2, 0x00, 0x00, 0x04, /* lmg %r0, %r15, 0x200(%r15) */
1099 /* Writes instructions to target, updating the to pointer. */
1101 static void
1102 append_insns (CORE_ADDR *to, size_t len, const unsigned char *buf)
1104 target_write_memory (*to, buf, len);
1105 *to += len;
1108 /* Relocates an instruction from oldloc to *to, updating to. */
1110 static int
1111 s390_relocate_instruction (CORE_ADDR *to, CORE_ADDR oldloc, int is_64)
1113 gdb_byte buf[6];
1114 int ilen;
1115 int op2;
1116 /* 0: no fixup, 1: PC16DBL fixup, 2: PC32DBL fixup. */
1117 int mode = 0;
1118 int is_bras = 0;
1119 read_inferior_memory (oldloc, buf, sizeof buf);
1120 if (buf[0] < 0x40)
1121 ilen = 2;
1122 else if (buf[0] < 0xc0)
1123 ilen = 4;
1124 else
1125 ilen = 6;
1126 switch (buf[0])
1128 case 0x05: /* BALR */
1129 case 0x0c: /* BASSM */
1130 case 0x0d: /* BASR */
1131 case 0x45: /* BAL */
1132 case 0x4d: /* BAS */
1133 /* These save a return address and mess around with registers.
1134 We can't relocate them. */
1135 return 1;
1136 case 0x84: /* BRXH */
1137 case 0x85: /* BRXLE */
1138 mode = 1;
1139 break;
1140 case 0xa7:
1141 op2 = buf[1] & 0xf;
1142 /* BRC, BRAS, BRCT, BRCTG */
1143 if (op2 >= 4 && op2 <= 7)
1144 mode = 1;
1145 /* BRAS */
1146 if (op2 == 5)
1147 is_bras = 1;
1148 break;
1149 case 0xc0:
1150 op2 = buf[1] & 0xf;
1151 /* LARL, BRCL, BRASL */
1152 if (op2 == 0 || op2 == 4 || op2 == 5)
1153 mode = 2;
1154 /* BRASL */
1155 if (op2 == 5)
1156 is_bras = 1;
1157 break;
1158 case 0xc4:
1159 case 0xc6:
1160 /* PC-relative addressing instructions. */
1161 mode = 2;
1162 break;
1163 case 0xc5: /* BPRP */
1164 case 0xc7: /* BPP */
1165 /* Branch prediction - just skip it. */
1166 return 0;
1167 case 0xcc:
1168 op2 = buf[1] & 0xf;
1169 /* BRCTH */
1170 if (op2 == 6)
1171 mode = 2;
1172 break;
1173 case 0xec:
1174 op2 = buf[5];
1175 switch (op2)
1177 case 0x44: /* BRXHG */
1178 case 0x45: /* BRXLG */
1179 case 0x64: /* CGRJ */
1180 case 0x65: /* CLGRJ */
1181 case 0x76: /* CRJ */
1182 case 0x77: /* CLRJ */
1183 mode = 1;
1184 break;
1186 break;
1189 if (mode != 0)
1191 /* We'll have to relocate an instruction with a PC-relative field.
1192 First, compute the target. */
1193 int64_t loffset = 0;
1194 CORE_ADDR target;
1195 if (mode == 1)
1197 int16_t soffset = 0;
1198 memcpy (&soffset, buf + 2, 2);
1199 loffset = soffset;
1201 else if (mode == 2)
1203 int32_t soffset = 0;
1204 memcpy (&soffset, buf + 2, 4);
1205 loffset = soffset;
1207 target = oldloc + loffset * 2;
1208 if (!is_64)
1209 target &= 0x7fffffff;
1211 if (is_bras)
1213 /* BRAS or BRASL was used. We cannot just relocate those, since
1214 they save the return address in a register. We can, however,
1215 replace them with a LARL+JG sequence. */
1217 /* Make the LARL. */
1218 int32_t soffset;
1219 buf[0] = 0xc0;
1220 buf[1] &= 0xf0;
1221 loffset = oldloc + ilen - *to;
1222 loffset >>= 1;
1223 soffset = loffset;
1224 if (soffset != loffset && is_64)
1225 return 1;
1226 memcpy (buf + 2, &soffset, 4);
1227 append_insns (to, 6, buf);
1229 /* Note: this is not fully correct. In 31-bit mode, LARL will write
1230 an address with the top bit 0, while BRAS/BRASL will write it
1231 with top bit 1. It should not matter much, since linux compilers
1232 use BR and not BSM to return from functions, but it could confuse
1233 some poor stack unwinder. */
1235 /* We'll now be writing a JG. */
1236 mode = 2;
1237 buf[0] = 0xc0;
1238 buf[1] = 0xf4;
1239 ilen = 6;
1242 /* Compute the new offset and write it to the buffer. */
1243 loffset = target - *to;
1244 loffset >>= 1;
1246 if (mode == 1)
1248 int16_t soffset = loffset;
1249 if (soffset != loffset)
1250 return 1;
1251 memcpy (buf + 2, &soffset, 2);
1253 else if (mode == 2)
1255 int32_t soffset = loffset;
1256 if (soffset != loffset && is_64)
1257 return 1;
1258 memcpy (buf + 2, &soffset, 4);
1261 append_insns (to, ilen, buf);
1262 return 0;
1265 bool
1266 s390_target::supports_fast_tracepoints ()
1268 return true;
1271 /* Implementation of target ops method
1272 "install_fast_tracepoint_jump_pad". */
1275 s390_target::install_fast_tracepoint_jump_pad
1276 (CORE_ADDR tpoint, CORE_ADDR tpaddr, CORE_ADDR collector,
1277 CORE_ADDR lockaddr, ULONGEST orig_size, CORE_ADDR *jump_entry,
1278 CORE_ADDR *trampoline, ULONGEST *trampoline_size,
1279 unsigned char *jjump_pad_insn, ULONGEST *jjump_pad_insn_size,
1280 CORE_ADDR *adjusted_insn_addr, CORE_ADDR *adjusted_insn_addr_end,
1281 char *err)
1283 int i;
1284 int64_t loffset;
1285 int32_t offset;
1286 unsigned char jbuf[6] = { 0xc0, 0xf4, 0, 0, 0, 0 }; /* jg ... */
1287 CORE_ADDR buildaddr = *jump_entry;
1288 #ifdef __s390x__
1289 struct regcache *regcache = get_thread_regcache (current_thread, 0);
1290 int is_64 = register_size (regcache->tdesc, 0) == 8;
1291 int is_zarch = is_64 || have_hwcap_s390_high_gprs;
1292 int has_vx = have_hwcap_s390_vx;
1293 #else
1294 int is_64 = 0, is_zarch = 0, has_vx = 0;
1295 #endif
1296 CORE_ADDR literals[4] = {
1297 tpaddr,
1298 tpoint,
1299 collector,
1300 lockaddr,
1303 /* First, store the GPRs. */
1304 if (is_zarch)
1305 append_insns (&buildaddr, sizeof s390_ft_entry_gpr_zarch,
1306 s390_ft_entry_gpr_zarch);
1307 else
1308 append_insns (&buildaddr, sizeof s390_ft_entry_gpr_esa,
1309 s390_ft_entry_gpr_esa);
1311 /* Second, misc registers (ARs, PSWM, FPC). PSWA will be stored below. */
1312 append_insns (&buildaddr, sizeof s390_ft_entry_misc, s390_ft_entry_misc);
1314 /* Third, FRs or VRs. */
1315 if (has_vx)
1316 append_insns (&buildaddr, sizeof s390_ft_entry_vr, s390_ft_entry_vr);
1317 else
1318 append_insns (&buildaddr, sizeof s390_ft_entry_fr, s390_ft_entry_fr);
1320 /* Now, the main part of code - store PSWA, take lock, call collector,
1321 leave lock. First, we'll need to fetch 4 literals. */
1322 if (is_64) {
1323 unsigned char buf[] = {
1324 0x07, 0x07, /* nopr %r7 */
1325 0x07, 0x07, /* nopr %r7 */
1326 0x07, 0x07, /* nopr %r7 */
1327 0xa7, 0x15, 0x00, 0x12, /* bras %r1, .Lend */
1328 0, 0, 0, 0, 0, 0, 0, 0, /* tpaddr */
1329 0, 0, 0, 0, 0, 0, 0, 0, /* tpoint */
1330 0, 0, 0, 0, 0, 0, 0, 0, /* collector */
1331 0, 0, 0, 0, 0, 0, 0, 0, /* lockaddr */
1332 /* .Lend: */
1334 /* Find the proper start place in buf, so that literals will be
1335 aligned. */
1336 int bufpos = (buildaddr + 2) & 7;
1337 /* Stuff the literals into the buffer. */
1338 for (i = 0; i < 4; i++) {
1339 uint64_t lit = literals[i];
1340 memcpy (&buf[sizeof buf - 32 + i * 8], &lit, 8);
1342 append_insns (&buildaddr, sizeof buf - bufpos, buf + bufpos);
1343 append_insns (&buildaddr, sizeof s390_ft_main_64, s390_ft_main_64);
1344 } else {
1345 unsigned char buf[] = {
1346 0x07, 0x07, /* nopr %r7 */
1347 0xa7, 0x15, 0x00, 0x0a, /* bras %r1, .Lend */
1348 0, 0, 0, 0, /* tpaddr */
1349 0, 0, 0, 0, /* tpoint */
1350 0, 0, 0, 0, /* collector */
1351 0, 0, 0, 0, /* lockaddr */
1352 /* .Lend: */
1354 /* Find the proper start place in buf, so that literals will be
1355 aligned. */
1356 int bufpos = (buildaddr + 2) & 3;
1357 /* First literal will be saved as the PSWA, make sure it has the high bit
1358 set. */
1359 literals[0] |= 0x80000000;
1360 /* Stuff the literals into the buffer. */
1361 for (i = 0; i < 4; i++) {
1362 uint32_t lit = literals[i];
1363 memcpy (&buf[sizeof buf - 16 + i * 4], &lit, 4);
1365 append_insns (&buildaddr, sizeof buf - bufpos, buf + bufpos);
1366 append_insns (&buildaddr, sizeof s390_ft_main_31, s390_ft_main_31);
1369 /* Restore FRs or VRs. */
1370 if (has_vx)
1371 append_insns (&buildaddr, sizeof s390_ft_exit_vr, s390_ft_exit_vr);
1372 else
1373 append_insns (&buildaddr, sizeof s390_ft_exit_fr, s390_ft_exit_fr);
1375 /* Restore misc registers. */
1376 append_insns (&buildaddr, sizeof s390_ft_exit_misc, s390_ft_exit_misc);
1378 /* Restore the GPRs. */
1379 if (is_zarch)
1380 append_insns (&buildaddr, sizeof s390_ft_exit_gpr_zarch,
1381 s390_ft_exit_gpr_zarch);
1382 else
1383 append_insns (&buildaddr, sizeof s390_ft_exit_gpr_esa,
1384 s390_ft_exit_gpr_esa);
1386 /* Now, adjust the original instruction to execute in the jump
1387 pad. */
1388 *adjusted_insn_addr = buildaddr;
1389 if (s390_relocate_instruction (&buildaddr, tpaddr, is_64))
1391 sprintf (err, "E.Could not relocate instruction for tracepoint.");
1392 return 1;
1394 *adjusted_insn_addr_end = buildaddr;
1396 /* Finally, write a jump back to the program. */
1398 loffset = (tpaddr + orig_size) - buildaddr;
1399 loffset >>= 1;
1400 offset = loffset;
1401 if (is_64 && offset != loffset)
1403 sprintf (err,
1404 "E.Jump back from jump pad too far from tracepoint "
1405 "(offset 0x%" PRIx64 " > int33).", loffset);
1406 return 1;
1408 memcpy (jbuf + 2, &offset, 4);
1409 append_insns (&buildaddr, sizeof jbuf, jbuf);
1411 /* The jump pad is now built. Wire in a jump to our jump pad. This
1412 is always done last (by our caller actually), so that we can
1413 install fast tracepoints with threads running. This relies on
1414 the agent's atomic write support. */
1415 loffset = *jump_entry - tpaddr;
1416 loffset >>= 1;
1417 offset = loffset;
1418 if (is_64 && offset != loffset)
1420 sprintf (err,
1421 "E.Jump back from jump pad too far from tracepoint "
1422 "(offset 0x%" PRIx64 " > int33).", loffset);
1423 return 1;
1425 memcpy (jbuf + 2, &offset, 4);
1426 memcpy (jjump_pad_insn, jbuf, sizeof jbuf);
1427 *jjump_pad_insn_size = sizeof jbuf;
1429 /* Return the end address of our pad. */
1430 *jump_entry = buildaddr;
1432 return 0;
1435 /* Implementation of target ops method
1436 "get_min_fast_tracepoint_insn_len". */
1439 s390_target::get_min_fast_tracepoint_insn_len ()
1441 /* We only support using 6-byte jumps to reach the tracepoint code.
1442 If the tracepoint buffer were allocated sufficiently close (64kiB)
1443 to the executable code, and the traced instruction itself was close
1444 enough to the beginning, we could use 4-byte jumps, but this doesn't
1445 seem to be worth the effort. */
1446 return 6;
1449 /* Implementation of target ops method "get_ipa_tdesc_idx". */
1452 s390_target::get_ipa_tdesc_idx ()
1454 struct regcache *regcache = get_thread_regcache (current_thread, 0);
1455 const struct target_desc *tdesc = regcache->tdesc;
1457 #ifdef __s390x__
1458 if (tdesc == tdesc_s390x_linux64)
1459 return S390_TDESC_64;
1460 if (tdesc == tdesc_s390x_linux64v1)
1461 return S390_TDESC_64V1;
1462 if (tdesc == tdesc_s390x_linux64v2)
1463 return S390_TDESC_64V2;
1464 if (tdesc == tdesc_s390x_te_linux64)
1465 return S390_TDESC_TE;
1466 if (tdesc == tdesc_s390x_vx_linux64)
1467 return S390_TDESC_VX;
1468 if (tdesc == tdesc_s390x_tevx_linux64)
1469 return S390_TDESC_TEVX;
1470 if (tdesc == tdesc_s390x_gs_linux64)
1471 return S390_TDESC_GS;
1472 #endif
1474 if (tdesc == tdesc_s390_linux32)
1475 return S390_TDESC_32;
1476 if (tdesc == tdesc_s390_linux32v1)
1477 return S390_TDESC_32V1;
1478 if (tdesc == tdesc_s390_linux32v2)
1479 return S390_TDESC_32V2;
1480 if (tdesc == tdesc_s390_linux64)
1481 return S390_TDESC_64;
1482 if (tdesc == tdesc_s390_linux64v1)
1483 return S390_TDESC_64V1;
1484 if (tdesc == tdesc_s390_linux64v2)
1485 return S390_TDESC_64V2;
1486 if (tdesc == tdesc_s390_te_linux64)
1487 return S390_TDESC_TE;
1488 if (tdesc == tdesc_s390_vx_linux64)
1489 return S390_TDESC_VX;
1490 if (tdesc == tdesc_s390_tevx_linux64)
1491 return S390_TDESC_TEVX;
1492 if (tdesc == tdesc_s390_gs_linux64)
1493 return S390_TDESC_GS;
1495 return 0;
1498 /* Appends given buffer to current_insn_ptr in the target. */
1500 static void
1501 add_insns (const unsigned char *start, int len)
1503 CORE_ADDR buildaddr = current_insn_ptr;
1505 threads_debug_printf ("Adding %d bytes of insn at %s",
1506 len, paddress (buildaddr));
1508 append_insns (&buildaddr, len, start);
1509 current_insn_ptr = buildaddr;
1512 /* Register usage in emit:
1514 - %r0, %r1: temp
1515 - %r2: top of stack (high word for 31-bit)
1516 - %r3: low word of top of stack (for 31-bit)
1517 - %r4, %r5: temp
1518 - %r6, %r7, %r8: don't use
1519 - %r9: saved arg1
1520 - %r10: saved arg2
1521 - %r11: frame pointer
1522 - %r12: saved top of stack for void_call_2 (high word for 31-bit)
1523 - %r13: low word of saved top of stack (for 31-bit)
1524 - %r14: return address for calls
1525 - %r15: stack pointer
1529 /* The "emit_prologue" emit_ops method for s390. */
1531 static void
1532 s390_emit_prologue (void)
1534 static const unsigned char buf[] = {
1535 0x90, 0x9f, 0xf0, 0x24, /* stm %r9, %r15, 0x24(%r15) */
1536 0x18, 0x92, /* lr %r9, %r2 */
1537 0x18, 0xa3, /* lr %r10, %r3 */
1538 0x18, 0xbf, /* lr %r11, %r15 */
1540 add_insns (buf, sizeof buf);
1543 /* The "emit_epilogue" emit_ops method for s390. */
1545 static void
1546 s390_emit_epilogue (void)
1548 static const unsigned char buf[] = {
1549 0x90, 0x23, 0xa0, 0x00, /* stm %r2, %r3, 0(%r10) */
1550 0xa7, 0x28, 0x00, 0x00, /* lhi %r2, 0 */
1551 0x98, 0x9f, 0xb0, 0x24, /* lm %r9, %r15, 0x24(%r11) */
1552 0x07, 0xfe, /* br %r14 */
1554 add_insns (buf, sizeof buf);
1557 /* The "emit_add" emit_ops method for s390. */
1559 static void
1560 s390_emit_add (void)
1562 static const unsigned char buf[] = {
1563 0x5e, 0x30, 0xf0, 0x04, /* al %r3, 4(%r15) */
1564 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x98, /* al %r2, 0(%r15) */
1565 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1567 add_insns (buf, sizeof buf);
1570 /* The "emit_sub" emit_ops method for s390. */
1572 static void
1573 s390_emit_sub (void)
1575 static const unsigned char buf[] = {
1576 0x98, 0x45, 0xf0, 0x00, /* lm %r4, %r5, 0(%r15) */
1577 0x1f, 0x53, /* slr %r5, %r3 */
1578 0xb9, 0x99, 0x00, 0x42, /* slbr %r4, %r2 */
1579 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1580 0x18, 0x35, /* lr %r3, %r5 */
1581 0x18, 0x24, /* lr %r2, %r4 */
1583 add_insns (buf, sizeof buf);
1586 /* The "emit_mul" emit_ops method for s390. */
1588 static void
1589 s390_emit_mul (void)
1591 emit_error = 1;
1594 /* The "emit_lsh" emit_ops method for s390. */
1596 static void
1597 s390_emit_lsh (void)
1599 static const unsigned char buf[] = {
1600 0x18, 0x43, /* lr %r4, %r3 */
1601 0x98, 0x23, 0xf0, 0x00, /* lm %r2, %r3, 0(%r15) */
1602 0x8d, 0x20, 0x40, 0x00, /* sldl %r2, 0(%r4) */
1603 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1605 add_insns (buf, sizeof buf);
1608 /* The "emit_rsh_signed" emit_ops method for s390. */
1610 static void
1611 s390_emit_rsh_signed (void)
1613 static const unsigned char buf[] = {
1614 0x18, 0x43, /* lr %r4, %r3 */
1615 0x98, 0x23, 0xf0, 0x00, /* lm %r2, %r3, 0(%r15) */
1616 0x8e, 0x20, 0x40, 0x00, /* srda %r2, 0(%r4) */
1617 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1619 add_insns (buf, sizeof buf);
1622 /* The "emit_rsh_unsigned" emit_ops method for s390. */
1624 static void
1625 s390_emit_rsh_unsigned (void)
1627 static const unsigned char buf[] = {
1628 0x18, 0x43, /* lr %r4, %r3 */
1629 0x98, 0x23, 0xf0, 0x00, /* lm %r2, %r3, 0(%r15) */
1630 0x8c, 0x20, 0x40, 0x00, /* srdl %r2, 0(%r4) */
1631 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1633 add_insns (buf, sizeof buf);
1636 /* The "emit_ext" emit_ops method for s390. */
1638 static void
1639 s390_emit_ext (int arg)
1641 unsigned char buf[] = {
1642 0x8d, 0x20, 0x00, (unsigned char) (64 - arg), /* sldl %r2, <64-arg> */
1643 0x8e, 0x20, 0x00, (unsigned char) (64 - arg), /* srda %r2, <64-arg> */
1645 add_insns (buf, sizeof buf);
1648 /* The "emit_log_not" emit_ops method for s390. */
1650 static void
1651 s390_emit_log_not (void)
1653 static const unsigned char buf[] = {
1654 0x16, 0x23, /* or %r2, %r3 */
1655 0xa7, 0x28, 0x00, 0x00, /* lhi %r2, 0 */
1656 0xa7, 0x38, 0x00, 0x00, /* lhi %r3, 0 */
1657 0xa7, 0x74, 0x00, 0x04, /* jne .Lskip */
1658 0xa7, 0x38, 0x00, 0x01, /* lhi %r3, 1 */
1659 /* .Lskip: */
1661 add_insns (buf, sizeof buf);
1664 /* The "emit_bit_and" emit_ops method for s390. */
1666 static void
1667 s390_emit_bit_and (void)
1669 static const unsigned char buf[] = {
1670 0x54, 0x20, 0xf0, 0x00, /* n %r2, 0(%r15) */
1671 0x54, 0x30, 0xf0, 0x04, /* n %r3, 4(%r15) */
1672 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1674 add_insns (buf, sizeof buf);
1677 /* The "emit_bit_or" emit_ops method for s390. */
1679 static void
1680 s390_emit_bit_or (void)
1682 static const unsigned char buf[] = {
1683 0x56, 0x20, 0xf0, 0x00, /* o %r2, 0(%r15) */
1684 0x56, 0x30, 0xf0, 0x04, /* o %r3, 4(%r15) */
1685 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1687 add_insns (buf, sizeof buf);
1690 /* The "emit_bit_xor" emit_ops method for s390. */
1692 static void
1693 s390_emit_bit_xor (void)
1695 static const unsigned char buf[] = {
1696 0x57, 0x20, 0xf0, 0x00, /* x %r2, 0(%r15) */
1697 0x57, 0x30, 0xf0, 0x04, /* x %r3, 4(%r15) */
1698 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1700 add_insns (buf, sizeof buf);
1703 /* The "emit_bit_not" emit_ops method for s390. */
1705 static void
1706 s390_emit_bit_not (void)
1708 static const unsigned char buf[] = {
1709 0xa7, 0x48, 0xff, 0xff, /* lhi %r4, -1 */
1710 0x17, 0x24, /* xr %r2, %r4 */
1711 0x17, 0x34, /* xr %r3, %r4 */
1713 add_insns (buf, sizeof buf);
1716 /* The "emit_equal" emit_ops method for s390. */
1718 static void
1719 s390_emit_equal (void)
1721 s390_emit_bit_xor ();
1722 s390_emit_log_not ();
1725 /* The "emit_less_signed" emit_ops method for s390. */
1727 static void
1728 s390_emit_less_signed (void)
1730 static const unsigned char buf[] = {
1731 0x59, 0x20, 0xf0, 0x00, /* c %r2, 0(%r15) */
1732 0xa7, 0x24, 0x00, 0x0c, /* jh .Lless */
1733 0xa7, 0x44, 0x00, 0x06, /* jl .Lhigh */
1734 0x55, 0x30, 0xf0, 0x04, /* cl %r3, 4(%r15) */
1735 0xa7, 0x24, 0x00, 0x06, /* jh .Lless */
1736 /* .Lhigh: */
1737 0xa7, 0x38, 0x00, 0x00, /* lhi %r3, 0 */
1738 0xa7, 0xf4, 0x00, 0x04, /* j .Lend */
1739 /* .Lless: */
1740 0xa7, 0x38, 0x00, 0x01, /* lhi %r3, 1 */
1741 /* .Lend: */
1742 0xa7, 0x28, 0x00, 0x00, /* lhi %r2, 0 */
1743 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1745 add_insns (buf, sizeof buf);
1748 /* The "emit_less_unsigned" emit_ops method for s390. */
1750 static void
1751 s390_emit_less_unsigned (void)
1753 static const unsigned char buf[] = {
1754 0x55, 0x20, 0xf0, 0x00, /* cl %r2, 0(%r15) */
1755 0xa7, 0x24, 0x00, 0x0c, /* jh .Lless */
1756 0xa7, 0x44, 0x00, 0x06, /* jl .Lhigh */
1757 0x55, 0x30, 0xf0, 0x04, /* cl %r3, 4(%r15) */
1758 0xa7, 0x24, 0x00, 0x06, /* jh .Lless */
1759 /* .Lhigh: */
1760 0xa7, 0x38, 0x00, 0x00, /* lhi %r3, 0 */
1761 0xa7, 0xf4, 0x00, 0x04, /* j .Lend */
1762 /* .Lless: */
1763 0xa7, 0x38, 0x00, 0x01, /* lhi %r3, 1 */
1764 /* .Lend: */
1765 0xa7, 0x28, 0x00, 0x00, /* lhi %r2, 0 */
1766 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1768 add_insns (buf, sizeof buf);
1771 /* The "emit_ref" emit_ops method for s390. */
1773 static void
1774 s390_emit_ref (int size)
1776 static const unsigned char buf1[] = {
1777 0xa7, 0x28, 0x00, 0x00, /* lhi %r2, 0 */
1778 0x43, 0x30, 0x30, 0x00, /* ic %r3, 0(%r3) */
1780 static const unsigned char buf2[] = {
1781 0xa7, 0x28, 0x00, 0x00, /* lhi %r2, 0 */
1782 0x48, 0x30, 0x30, 0x00, /* lh %r3, 0(%r3) */
1784 static const unsigned char buf4[] = {
1785 0xa7, 0x28, 0x00, 0x00, /* lhi %r2, 0 */
1786 0x58, 0x30, 0x30, 0x00, /* l %r3, 0(%r3) */
1788 static const unsigned char buf8[] = {
1789 0x98, 0x23, 0x30, 0x00, /* lm %r2, %r3, 0(%r3) */
1791 switch (size)
1793 case 1:
1794 add_insns (buf1, sizeof buf1);
1795 break;
1796 case 2:
1797 add_insns (buf2, sizeof buf2);
1798 break;
1799 case 4:
1800 add_insns (buf4, sizeof buf4);
1801 break;
1802 case 8:
1803 add_insns (buf8, sizeof buf8);
1804 break;
1805 default:
1806 emit_error = 1;
1810 /* The "emit_if_goto" emit_ops method for s390. */
1812 static void
1813 s390_emit_if_goto (int *offset_p, int *size_p)
1815 static const unsigned char buf[] = {
1816 0x16, 0x23, /* or %r2, %r3 */
1817 0x98, 0x23, 0xf0, 0x00, /* lm %r2, %r3, 0(%r15) */
1818 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1819 0xc0, 0x74, 0x00, 0x00, 0x00, 0x00 /* jgne <fillme> */
1821 add_insns (buf, sizeof buf);
1822 if (offset_p)
1823 *offset_p = 12;
1824 if (size_p)
1825 *size_p = 4;
1828 /* The "emit_goto" emit_ops method for s390 and s390x. */
1830 static void
1831 s390_emit_goto (int *offset_p, int *size_p)
1833 static const unsigned char buf[] = {
1834 0xc0, 0xf4, 0x00, 0x00, 0x00, 0x00, /* jg <fillme> */
1836 add_insns (buf, sizeof buf);
1837 if (offset_p)
1838 *offset_p = 2;
1839 if (size_p)
1840 *size_p = 4;
1843 /* The "write_goto_address" emit_ops method for s390 and s390x. */
1845 static void
1846 s390_write_goto_address (CORE_ADDR from, CORE_ADDR to, int size)
1848 long diff = ((long) (to - (from - 2))) / 2;
1849 int sdiff = diff;
1850 unsigned char buf[sizeof sdiff];
1852 /* We're only doing 4-byte sizes at the moment. */
1853 if (size != sizeof sdiff || sdiff != diff)
1855 emit_error = 1;
1856 return;
1859 memcpy (buf, &sdiff, sizeof sdiff);
1860 target_write_memory (from, buf, sizeof sdiff);
1863 /* Preparation for emitting a literal pool of given size. Loads the address
1864 of the pool into %r1, and jumps over it. Called should emit the pool data
1865 immediately afterwards. Used for both s390 and s390x. */
1867 static void
1868 s390_emit_litpool (int size)
1870 static const unsigned char nop[] = {
1871 0x07, 0x07,
1873 unsigned char buf[] = {
1874 0xa7, 0x15, 0x00,
1875 (unsigned char) ((size + 4) / 2), /* bras %r1, .Lend+size */
1876 /* .Lend: */
1878 if (size == 4)
1880 /* buf needs to start at even halfword for litpool to be aligned */
1881 if (current_insn_ptr & 2)
1882 add_insns (nop, sizeof nop);
1884 else
1886 while ((current_insn_ptr & 6) != 4)
1887 add_insns (nop, sizeof nop);
1889 add_insns (buf, sizeof buf);
1892 /* The "emit_const" emit_ops method for s390. */
1894 static void
1895 s390_emit_const (LONGEST num)
1897 unsigned long long n = num;
1898 unsigned char buf_s[] = {
1899 /* lhi %r3, <num> */
1900 0xa7, 0x38,
1901 (unsigned char) (num >> 8), (unsigned char) num,
1902 /* xr %r2, %r2 */
1903 0x17, 0x22,
1905 static const unsigned char buf_l[] = {
1906 0x98, 0x23, 0x10, 0x00, /* lm %r2, %r3, 0(%r1) */
1908 if (num < 0x8000 && num >= 0)
1909 add_insns (buf_s, sizeof buf_s);
1910 else
1912 s390_emit_litpool (8);
1913 add_insns ((unsigned char *) &n, sizeof n);
1914 add_insns (buf_l, sizeof buf_l);
1918 /* The "emit_call" emit_ops method for s390. */
1920 static void
1921 s390_emit_call (CORE_ADDR fn)
1923 unsigned int n = fn;
1924 static const unsigned char buf[] = {
1925 0x58, 0x10, 0x10, 0x00, /* l %r1, 0(%r1) */
1926 0xa7, 0xfa, 0xff, 0xa0, /* ahi %r15, -0x60 */
1927 0x0d, 0xe1, /* basr %r14, %r1 */
1928 0xa7, 0xfa, 0x00, 0x60, /* ahi %r15, 0x60 */
1930 s390_emit_litpool (4);
1931 add_insns ((unsigned char *) &n, sizeof n);
1932 add_insns (buf, sizeof buf);
1935 /* The "emit_reg" emit_ops method for s390. */
1937 static void
1938 s390_emit_reg (int reg)
1940 unsigned char bufpre[] = {
1941 /* lr %r2, %r9 */
1942 0x18, 0x29,
1943 /* lhi %r3, <reg> */
1944 0xa7, 0x38, (unsigned char) (reg >> 8), (unsigned char) reg,
1946 add_insns (bufpre, sizeof bufpre);
1947 s390_emit_call (get_raw_reg_func_addr ());
1950 /* The "emit_pop" emit_ops method for s390. */
1952 static void
1953 s390_emit_pop (void)
1955 static const unsigned char buf[] = {
1956 0x98, 0x23, 0xf0, 0x00, /* lm %r2, %r3, 0(%r15) */
1957 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1959 add_insns (buf, sizeof buf);
1962 /* The "emit_stack_flush" emit_ops method for s390. */
1964 static void
1965 s390_emit_stack_flush (void)
1967 static const unsigned char buf[] = {
1968 0xa7, 0xfa, 0xff, 0xf8, /* ahi %r15, -8 */
1969 0x90, 0x23, 0xf0, 0x00, /* stm %r2, %r3, 0(%r15) */
1971 add_insns (buf, sizeof buf);
1974 /* The "emit_zero_ext" emit_ops method for s390. */
1976 static void
1977 s390_emit_zero_ext (int arg)
1979 unsigned char buf[] = {
1980 0x8d, 0x20, 0x00, (unsigned char) (64 - arg), /* sldl %r2, <64-arg> */
1981 0x8c, 0x20, 0x00, (unsigned char) (64 - arg), /* srdl %r2, <64-arg> */
1983 add_insns (buf, sizeof buf);
1986 /* The "emit_swap" emit_ops method for s390. */
1988 static void
1989 s390_emit_swap (void)
1991 static const unsigned char buf[] = {
1992 0x98, 0x45, 0xf0, 0x00, /* lm %r4, %r5, 0(%r15) */
1993 0x90, 0x23, 0xf0, 0x00, /* stm %r2, %r3, 0(%r15) */
1994 0x18, 0x24, /* lr %r2, %r4 */
1995 0x18, 0x35, /* lr %r3, %r5 */
1997 add_insns (buf, sizeof buf);
2000 /* The "emit_stack_adjust" emit_ops method for s390. */
2002 static void
2003 s390_emit_stack_adjust (int n)
2005 unsigned char buf[] = {
2006 /* ahi %r15, 8*n */
2007 0xa7, 0xfa,
2008 (unsigned char ) (n * 8 >> 8), (unsigned char) (n * 8),
2010 add_insns (buf, sizeof buf);
2013 /* Sets %r2 to a 32-bit constant. */
2015 static void
2016 s390_emit_set_r2 (int arg1)
2018 unsigned char buf_s[] = {
2019 /* lhi %r2, <arg1> */
2020 0xa7, 0x28, (unsigned char) (arg1 >> 8), (unsigned char) arg1,
2022 static const unsigned char buf_l[] = {
2023 0x58, 0x20, 0x10, 0x00, /* l %r2, 0(%r1) */
2025 if (arg1 < 0x8000 && arg1 >= -0x8000)
2026 add_insns (buf_s, sizeof buf_s);
2027 else
2029 s390_emit_litpool (4);
2030 add_insns ((unsigned char *) &arg1, sizeof arg1);
2031 add_insns (buf_l, sizeof buf_l);
2035 /* The "emit_int_call_1" emit_ops method for s390. */
2037 static void
2038 s390_emit_int_call_1 (CORE_ADDR fn, int arg1)
2040 /* FN's prototype is `LONGEST(*fn)(int)'. */
2041 s390_emit_set_r2 (arg1);
2042 s390_emit_call (fn);
2045 /* The "emit_void_call_2" emit_ops method for s390. */
2047 static void
2048 s390_emit_void_call_2 (CORE_ADDR fn, int arg1)
2050 /* FN's prototype is `void(*fn)(int,LONGEST)'. */
2051 static const unsigned char buf[] = {
2052 0x18, 0xc2, /* lr %r12, %r2 */
2053 0x18, 0xd3, /* lr %r13, %r3 */
2054 0x18, 0x43, /* lr %r4, %r3 */
2055 0x18, 0x32, /* lr %r3, %r2 */
2057 static const unsigned char buf2[] = {
2058 0x18, 0x2c, /* lr %r2, %r12 */
2059 0x18, 0x3d, /* lr %r3, %r13 */
2061 add_insns (buf, sizeof buf);
2062 s390_emit_set_r2 (arg1);
2063 s390_emit_call (fn);
2064 add_insns (buf2, sizeof buf2);
2067 /* The "emit_eq_goto" emit_ops method for s390. */
2069 static void
2070 s390_emit_eq_goto (int *offset_p, int *size_p)
2072 static const unsigned char buf[] = {
2073 0x57, 0x20, 0xf0, 0x00, /* x %r2, 0(%r15) */
2074 0x57, 0x30, 0xf0, 0x04, /* x %r3, 4(%r15) */
2075 0x16, 0x23, /* or %r2, %r3 */
2076 0x98, 0x23, 0xf0, 0x08, /* lm %r2, %r3, 8(%r15) */
2077 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2078 0xc0, 0x84, 0x00, 0x00, 0x00, 0x00, /* jge <fillme> */
2080 add_insns (buf, sizeof buf);
2081 if (offset_p)
2082 *offset_p = 20;
2083 if (size_p)
2084 *size_p = 4;
2087 /* The "emit_ne_goto" emit_ops method for s390. */
2089 static void
2090 s390_emit_ne_goto (int *offset_p, int *size_p)
2092 static const unsigned char buf[] = {
2093 0x57, 0x20, 0xf0, 0x00, /* x %r2, 0(%r15) */
2094 0x57, 0x30, 0xf0, 0x04, /* x %r3, 4(%r15) */
2095 0x16, 0x23, /* or %r2, %r3 */
2096 0x98, 0x23, 0xf0, 0x08, /* lm %r2, %r3, 8(%r15) */
2097 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2098 0xc0, 0x74, 0x00, 0x00, 0x00, 0x00, /* jgne <fillme> */
2100 add_insns (buf, sizeof buf);
2101 if (offset_p)
2102 *offset_p = 20;
2103 if (size_p)
2104 *size_p = 4;
2107 /* The "emit_lt_goto" emit_ops method for s390. */
2109 static void
2110 s390_emit_lt_goto (int *offset_p, int *size_p)
2112 static const unsigned char buf[] = {
2113 0x59, 0x20, 0xf0, 0x00, /* c %r2, 0(%r15) */
2114 0xa7, 0x24, 0x00, 0x0e, /* jh .Ltrue */
2115 0xa7, 0x44, 0x00, 0x06, /* jl .Lfalse */
2116 0x55, 0x30, 0xf0, 0x04, /* cl %r3, 4(%r15) */
2117 0xa7, 0x24, 0x00, 0x08, /* jh .Ltrue */
2118 /* .Lfalse: */
2119 0x98, 0x23, 0xf0, 0x08, /* lm %r2, %r3, 8(%r15) */
2120 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2121 0xa7, 0xf4, 0x00, 0x09, /* j .Lend */
2122 /* .Ltrue: */
2123 0x98, 0x23, 0xf0, 0x08, /* lm %r2, %r3, 8(%r15) */
2124 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2125 0xc0, 0xf4, 0x00, 0x00, 0x00, 0x00, /* jg <fillme> */
2126 /* .Lend: */
2128 add_insns (buf, sizeof buf);
2129 if (offset_p)
2130 *offset_p = 42;
2131 if (size_p)
2132 *size_p = 4;
2135 /* The "emit_le_goto" emit_ops method for s390. */
2137 static void
2138 s390_emit_le_goto (int *offset_p, int *size_p)
2140 static const unsigned char buf[] = {
2141 0x59, 0x20, 0xf0, 0x00, /* c %r2, 0(%r15) */
2142 0xa7, 0x24, 0x00, 0x0e, /* jh .Ltrue */
2143 0xa7, 0x44, 0x00, 0x06, /* jl .Lfalse */
2144 0x55, 0x30, 0xf0, 0x04, /* cl %r3, 4(%r15) */
2145 0xa7, 0xa4, 0x00, 0x08, /* jhe .Ltrue */
2146 /* .Lfalse: */
2147 0x98, 0x23, 0xf0, 0x08, /* lm %r2, %r3, 8(%r15) */
2148 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2149 0xa7, 0xf4, 0x00, 0x09, /* j .Lend */
2150 /* .Ltrue: */
2151 0x98, 0x23, 0xf0, 0x08, /* lm %r2, %r3, 8(%r15) */
2152 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2153 0xc0, 0xf4, 0x00, 0x00, 0x00, 0x00, /* jg <fillme> */
2154 /* .Lend: */
2156 add_insns (buf, sizeof buf);
2157 if (offset_p)
2158 *offset_p = 42;
2159 if (size_p)
2160 *size_p = 4;
2163 /* The "emit_gt_goto" emit_ops method for s390. */
2165 static void
2166 s390_emit_gt_goto (int *offset_p, int *size_p)
2168 static const unsigned char buf[] = {
2169 0x59, 0x20, 0xf0, 0x00, /* c %r2, 0(%r15) */
2170 0xa7, 0x44, 0x00, 0x0e, /* jl .Ltrue */
2171 0xa7, 0x24, 0x00, 0x06, /* jh .Lfalse */
2172 0x55, 0x30, 0xf0, 0x04, /* cl %r3, 4(%r15) */
2173 0xa7, 0x44, 0x00, 0x08, /* jl .Ltrue */
2174 /* .Lfalse: */
2175 0x98, 0x23, 0xf0, 0x08, /* lm %r2, %r3, 8(%r15) */
2176 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2177 0xa7, 0xf4, 0x00, 0x09, /* j .Lend */
2178 /* .Ltrue: */
2179 0x98, 0x23, 0xf0, 0x08, /* lm %r2, %r3, 8(%r15) */
2180 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2181 0xc0, 0xf4, 0x00, 0x00, 0x00, 0x00, /* jg <fillme> */
2182 /* .Lend: */
2184 add_insns (buf, sizeof buf);
2185 if (offset_p)
2186 *offset_p = 42;
2187 if (size_p)
2188 *size_p = 4;
2191 /* The "emit_ge_goto" emit_ops method for s390. */
2193 static void
2194 s390_emit_ge_goto (int *offset_p, int *size_p)
2196 static const unsigned char buf[] = {
2197 0x59, 0x20, 0xf0, 0x00, /* c %r2, 0(%r15) */
2198 0xa7, 0x44, 0x00, 0x0e, /* jl .Ltrue */
2199 0xa7, 0x24, 0x00, 0x06, /* jh .Lfalse */
2200 0x55, 0x30, 0xf0, 0x04, /* cl %r3, 4(%r15) */
2201 0xa7, 0xc4, 0x00, 0x08, /* jle .Ltrue */
2202 /* .Lfalse: */
2203 0x98, 0x23, 0xf0, 0x08, /* lm %r2, %r3, 8(%r15) */
2204 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2205 0xa7, 0xf4, 0x00, 0x09, /* j .Lend */
2206 /* .Ltrue: */
2207 0x98, 0x23, 0xf0, 0x08, /* lm %r2, %r3, 8(%r15) */
2208 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2209 0xc0, 0xf4, 0x00, 0x00, 0x00, 0x00, /* jg <fillme> */
2210 /* .Lend: */
2212 add_insns (buf, sizeof buf);
2213 if (offset_p)
2214 *offset_p = 42;
2215 if (size_p)
2216 *size_p = 4;
2219 /* The "emit_ops" structure for s390. Named _impl to avoid name
2220 collision with s390_emit_ops function. */
2222 static struct emit_ops s390_emit_ops_impl =
2224 s390_emit_prologue,
2225 s390_emit_epilogue,
2226 s390_emit_add,
2227 s390_emit_sub,
2228 s390_emit_mul,
2229 s390_emit_lsh,
2230 s390_emit_rsh_signed,
2231 s390_emit_rsh_unsigned,
2232 s390_emit_ext,
2233 s390_emit_log_not,
2234 s390_emit_bit_and,
2235 s390_emit_bit_or,
2236 s390_emit_bit_xor,
2237 s390_emit_bit_not,
2238 s390_emit_equal,
2239 s390_emit_less_signed,
2240 s390_emit_less_unsigned,
2241 s390_emit_ref,
2242 s390_emit_if_goto,
2243 s390_emit_goto,
2244 s390_write_goto_address,
2245 s390_emit_const,
2246 s390_emit_call,
2247 s390_emit_reg,
2248 s390_emit_pop,
2249 s390_emit_stack_flush,
2250 s390_emit_zero_ext,
2251 s390_emit_swap,
2252 s390_emit_stack_adjust,
2253 s390_emit_int_call_1,
2254 s390_emit_void_call_2,
2255 s390_emit_eq_goto,
2256 s390_emit_ne_goto,
2257 s390_emit_lt_goto,
2258 s390_emit_le_goto,
2259 s390_emit_gt_goto,
2260 s390_emit_ge_goto
2263 #ifdef __s390x__
2265 /* The "emit_prologue" emit_ops method for s390x. */
2267 static void
2268 s390x_emit_prologue (void)
2270 static const unsigned char buf[] = {
2271 0xeb, 0x9f, 0xf0, 0x48, 0x00, 0x24, /* stmg %r9, %r15, 0x48(%r15) */
2272 0xb9, 0x04, 0x00, 0x92, /* lgr %r9, %r2 */
2273 0xb9, 0x04, 0x00, 0xa3, /* lgr %r10, %r3 */
2274 0xb9, 0x04, 0x00, 0xbf, /* lgr %r11, %r15 */
2276 add_insns (buf, sizeof buf);
2279 /* The "emit_epilogue" emit_ops method for s390x. */
2281 static void
2282 s390x_emit_epilogue (void)
2284 static const unsigned char buf[] = {
2285 0xe3, 0x20, 0xa0, 0x00, 0x00, 0x24, /* stg %r2, 0(%r10) */
2286 0xa7, 0x29, 0x00, 0x00, /* lghi %r2, 0 */
2287 0xeb, 0x9f, 0xf0, 0x48, 0x00, 0x04, /* lmg %r9, %r15, 0x48(%r15) */
2288 0x07, 0xfe, /* br %r14 */
2290 add_insns (buf, sizeof buf);
2293 /* The "emit_add" emit_ops method for s390x. */
2295 static void
2296 s390x_emit_add (void)
2298 static const unsigned char buf[] = {
2299 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x0a, /* alg %r2, 0(%r15) */
2300 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
2302 add_insns (buf, sizeof buf);
2305 /* The "emit_sub" emit_ops method for s390x. */
2307 static void
2308 s390x_emit_sub (void)
2310 static const unsigned char buf[] = {
2311 0xe3, 0x30, 0xf0, 0x00, 0x00, 0x04, /* lg %r3, 0(%r15) */
2312 0xb9, 0x0b, 0x00, 0x32, /* slgr %r3, %r2 */
2313 0xb9, 0x04, 0x00, 0x23, /* lgr %r2, %r3 */
2314 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
2316 add_insns (buf, sizeof buf);
2319 /* The "emit_mul" emit_ops method for s390x. */
2321 static void
2322 s390x_emit_mul (void)
2324 emit_error = 1;
2327 /* The "emit_lsh" emit_ops method for s390x. */
2329 static void
2330 s390x_emit_lsh (void)
2332 static const unsigned char buf[] = {
2333 0xe3, 0x30, 0xf0, 0x00, 0x00, 0x04, /* lg %r3, 0(%r15) */
2334 0xeb, 0x23, 0x20, 0x00, 0x00, 0x0d, /* sllg %r2, %r3, 0(%r2) */
2335 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
2337 add_insns (buf, sizeof buf);
2340 /* The "emit_rsh_signed" emit_ops method for s390x. */
2342 static void
2343 s390x_emit_rsh_signed (void)
2345 static const unsigned char buf[] = {
2346 0xe3, 0x30, 0xf0, 0x00, 0x00, 0x04, /* lg %r3, 0(%r15) */
2347 0xeb, 0x23, 0x20, 0x00, 0x00, 0x0a, /* srag %r2, %r3, 0(%r2) */
2348 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
2350 add_insns (buf, sizeof buf);
2353 /* The "emit_rsh_unsigned" emit_ops method for s390x. */
2355 static void
2356 s390x_emit_rsh_unsigned (void)
2358 static const unsigned char buf[] = {
2359 0xe3, 0x30, 0xf0, 0x00, 0x00, 0x04, /* lg %r3, 0(%r15) */
2360 0xeb, 0x23, 0x20, 0x00, 0x00, 0x0c, /* srlg %r2, %r3, 0(%r2) */
2361 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
2363 add_insns (buf, sizeof buf);
2366 /* The "emit_ext" emit_ops method for s390x. */
2368 static void
2369 s390x_emit_ext (int arg)
2371 unsigned char buf[] = {
2372 /* sllg %r2, %r2, <64-arg> */
2373 0xeb, 0x22, 0x00, (unsigned char) (64 - arg), 0x00, 0x0d,
2374 /* srag %r2, %r2, <64-arg> */
2375 0xeb, 0x22, 0x00, (unsigned char) (64 - arg), 0x00, 0x0a,
2377 add_insns (buf, sizeof buf);
2380 /* The "emit_log_not" emit_ops method for s390x. */
2382 static void
2383 s390x_emit_log_not (void)
2385 static const unsigned char buf[] = {
2386 0xb9, 0x00, 0x00, 0x22, /* lpgr %r2, %r2 */
2387 0xa7, 0x2b, 0xff, 0xff, /* aghi %r2, -1 */
2388 0xeb, 0x22, 0x00, 0x3f, 0x00, 0x0c, /* srlg %r2, %r2, 63 */
2390 add_insns (buf, sizeof buf);
2393 /* The "emit_bit_and" emit_ops method for s390x. */
2395 static void
2396 s390x_emit_bit_and (void)
2398 static const unsigned char buf[] = {
2399 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x80, /* ng %r2, 0(%r15) */
2400 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
2402 add_insns (buf, sizeof buf);
2405 /* The "emit_bit_or" emit_ops method for s390x. */
2407 static void
2408 s390x_emit_bit_or (void)
2410 static const unsigned char buf[] = {
2411 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x81, /* og %r2, 0(%r15) */
2412 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
2414 add_insns (buf, sizeof buf);
2417 /* The "emit_bit_xor" emit_ops method for s390x. */
2419 static void
2420 s390x_emit_bit_xor (void)
2422 static const unsigned char buf[] = {
2423 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x82, /* xg %r2, 0(%r15) */
2424 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
2426 add_insns (buf, sizeof buf);
2429 /* The "emit_bit_not" emit_ops method for s390x. */
2431 static void
2432 s390x_emit_bit_not (void)
2434 static const unsigned char buf[] = {
2435 0xa7, 0x39, 0xff, 0xff, /* lghi %r3, -1 */
2436 0xb9, 0x82, 0x00, 0x23, /* xgr %r2, %r3 */
2438 add_insns (buf, sizeof buf);
2441 /* The "emit_equal" emit_ops method for s390x. */
2443 static void
2444 s390x_emit_equal (void)
2446 s390x_emit_bit_xor ();
2447 s390x_emit_log_not ();
2450 /* The "emit_less_signed" emit_ops method for s390x. */
2452 static void
2453 s390x_emit_less_signed (void)
2455 static const unsigned char buf[] = {
2456 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20, /* cg %r2, 0(%r15) */
2457 0xa7, 0x29, 0x00, 0x01, /* lghi %r2, 1 */
2458 0xa7, 0x24, 0x00, 0x04, /* jh .Lend */
2459 0xa7, 0x29, 0x00, 0x00, /* lghi %r2, 0 */
2460 /* .Lend: */
2461 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
2463 add_insns (buf, sizeof buf);
2466 /* The "emit_less_unsigned" emit_ops method for s390x. */
2468 static void
2469 s390x_emit_less_unsigned (void)
2471 static const unsigned char buf[] = {
2472 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x21, /* clg %r2, 0(%r15) */
2473 0xa7, 0x29, 0x00, 0x01, /* lghi %r2, 1 */
2474 0xa7, 0x24, 0x00, 0x04, /* jh .Lend */
2475 0xa7, 0x29, 0x00, 0x00, /* lghi %r2, 0 */
2476 /* .Lend: */
2477 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
2479 add_insns (buf, sizeof buf);
2482 /* The "emit_ref" emit_ops method for s390x. */
2484 static void
2485 s390x_emit_ref (int size)
2487 static const unsigned char buf1[] = {
2488 0xe3, 0x20, 0x20, 0x00, 0x00, 0x90, /* llgc %r2, 0(%r2) */
2490 static const unsigned char buf2[] = {
2491 0xe3, 0x20, 0x20, 0x00, 0x00, 0x91 /* llgh %r2, 0(%r2) */
2493 static const unsigned char buf4[] = {
2494 0xe3, 0x20, 0x20, 0x00, 0x00, 0x16, /* llgf %r2, 0(%r2) */
2496 static const unsigned char buf8[] = {
2497 0xe3, 0x20, 0x20, 0x00, 0x00, 0x04, /* lg %r2, 0(%r2) */
2499 switch (size)
2501 case 1:
2502 add_insns (buf1, sizeof buf1);
2503 break;
2504 case 2:
2505 add_insns (buf2, sizeof buf2);
2506 break;
2507 case 4:
2508 add_insns (buf4, sizeof buf4);
2509 break;
2510 case 8:
2511 add_insns (buf8, sizeof buf8);
2512 break;
2513 default:
2514 emit_error = 1;
2518 /* The "emit_if_goto" emit_ops method for s390x. */
2520 static void
2521 s390x_emit_if_goto (int *offset_p, int *size_p)
2523 static const unsigned char buf[] = {
2524 0xb9, 0x02, 0x00, 0x22, /* ltgr %r2, %r2 */
2525 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x04, /* lg %r2, 0(%r15) */
2526 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
2527 0xc0, 0x74, 0x00, 0x00, 0x00, 0x00, /* jgne <fillme> */
2529 add_insns (buf, sizeof buf);
2530 if (offset_p)
2531 *offset_p = 16;
2532 if (size_p)
2533 *size_p = 4;
2536 /* The "emit_const" emit_ops method for s390x. */
2538 static void
2539 s390x_emit_const (LONGEST num)
2541 unsigned long long n = num;
2542 unsigned char buf_s[] = {
2543 /* lghi %r2, <num> */
2544 0xa7, 0x29, (unsigned char) (num >> 8), (unsigned char) num,
2546 static const unsigned char buf_l[] = {
2547 0xe3, 0x20, 0x10, 0x00, 0x00, 0x04, /* lg %r2, 0(%r1) */
2549 if (num < 0x8000 && num >= -0x8000)
2550 add_insns (buf_s, sizeof buf_s);
2551 else
2553 s390_emit_litpool (8);
2554 add_insns ((unsigned char *) &n, sizeof n);
2555 add_insns (buf_l, sizeof buf_l);
2559 /* The "emit_call" emit_ops method for s390x. */
2561 static void
2562 s390x_emit_call (CORE_ADDR fn)
2564 unsigned long n = fn;
2565 static const unsigned char buf[] = {
2566 0xe3, 0x10, 0x10, 0x00, 0x00, 0x04, /* lg %r1, 0(%r1) */
2567 0xa7, 0xfb, 0xff, 0x60, /* aghi %r15, -0xa0 */
2568 0x0d, 0xe1, /* basr %r14, %r1 */
2569 0xa7, 0xfb, 0x00, 0xa0, /* aghi %r15, 0xa0 */
2571 s390_emit_litpool (8);
2572 add_insns ((unsigned char *) &n, sizeof n);
2573 add_insns (buf, sizeof buf);
2576 /* The "emit_reg" emit_ops method for s390x. */
2578 static void
2579 s390x_emit_reg (int reg)
2581 unsigned char buf[] = {
2582 /* lgr %r2, %r9 */
2583 0xb9, 0x04, 0x00, 0x29,
2584 /* lghi %r3, <reg> */
2585 0xa7, 0x39, (unsigned char) (reg >> 8), (unsigned char) reg,
2587 add_insns (buf, sizeof buf);
2588 s390x_emit_call (get_raw_reg_func_addr ());
2591 /* The "emit_pop" emit_ops method for s390x. */
2593 static void
2594 s390x_emit_pop (void)
2596 static const unsigned char buf[] = {
2597 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x04, /* lg %r2, 0(%r15) */
2598 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
2600 add_insns (buf, sizeof buf);
2603 /* The "emit_stack_flush" emit_ops method for s390x. */
2605 static void
2606 s390x_emit_stack_flush (void)
2608 static const unsigned char buf[] = {
2609 0xa7, 0xfb, 0xff, 0xf8, /* aghi %r15, -8 */
2610 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x24, /* stg %r2, 0(%r15) */
2612 add_insns (buf, sizeof buf);
2615 /* The "emit_zero_ext" emit_ops method for s390x. */
2617 static void
2618 s390x_emit_zero_ext (int arg)
2620 unsigned char buf[] = {
2621 /* sllg %r2, %r2, <64-arg> */
2622 0xeb, 0x22, 0x00, (unsigned char) (64 - arg), 0x00, 0x0d,
2623 /* srlg %r2, %r2, <64-arg> */
2624 0xeb, 0x22, 0x00, (unsigned char) (64 - arg), 0x00, 0x0c,
2626 add_insns (buf, sizeof buf);
2629 /* The "emit_swap" emit_ops method for s390x. */
2631 static void
2632 s390x_emit_swap (void)
2634 static const unsigned char buf[] = {
2635 0xe3, 0x30, 0xf0, 0x00, 0x00, 0x04, /* lg %r3, 0(%r15) */
2636 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x24, /* stg %r2, 0(%r15) */
2637 0xb9, 0x04, 0x00, 0x23, /* lgr %r2, %r3 */
2639 add_insns (buf, sizeof buf);
2642 /* The "emit_stack_adjust" emit_ops method for s390x. */
2644 static void
2645 s390x_emit_stack_adjust (int n)
2647 unsigned char buf[] = {
2648 /* aghi %r15, 8*n */
2649 0xa7, 0xfb,
2650 (unsigned char) (n * 8 >> 8), (unsigned char) (n * 8),
2652 add_insns (buf, sizeof buf);
2655 /* The "emit_int_call_1" emit_ops method for s390x. */
2657 static void
2658 s390x_emit_int_call_1 (CORE_ADDR fn, int arg1)
2660 /* FN's prototype is `LONGEST(*fn)(int)'. */
2661 s390x_emit_const (arg1);
2662 s390x_emit_call (fn);
2665 /* The "emit_void_call_2" emit_ops method for s390x. */
2667 static void
2668 s390x_emit_void_call_2 (CORE_ADDR fn, int arg1)
2670 /* FN's prototype is `void(*fn)(int,LONGEST)'. */
2671 static const unsigned char buf[] = {
2672 0xb9, 0x04, 0x00, 0x32, /* lgr %r3, %r2 */
2673 0xb9, 0x04, 0x00, 0xc2, /* lgr %r12, %r2 */
2675 static const unsigned char buf2[] = {
2676 0xb9, 0x04, 0x00, 0x2c, /* lgr %r2, %r12 */
2678 add_insns (buf, sizeof buf);
2679 s390x_emit_const (arg1);
2680 s390x_emit_call (fn);
2681 add_insns (buf2, sizeof buf2);
2684 /* The "emit_eq_goto" emit_ops method for s390x. */
2686 static void
2687 s390x_emit_eq_goto (int *offset_p, int *size_p)
2689 static const unsigned char buf[] = {
2690 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20, /* cg %r2, 0(%r15) */
2691 0xe3, 0x20, 0xf0, 0x08, 0x00, 0x04, /* lg %r2, 8(%r15) */
2692 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2693 0xc0, 0x84, 0x00, 0x00, 0x00, 0x00, /* jge <fillme> */
2695 add_insns (buf, sizeof buf);
2696 if (offset_p)
2697 *offset_p = 18;
2698 if (size_p)
2699 *size_p = 4;
2702 /* The "emit_ne_goto" emit_ops method for s390x. */
2704 static void
2705 s390x_emit_ne_goto (int *offset_p, int *size_p)
2707 static const unsigned char buf[] = {
2708 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20, /* cg %r2, 0(%r15) */
2709 0xe3, 0x20, 0xf0, 0x08, 0x00, 0x04, /* lg %r2, 8(%r15) */
2710 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2711 0xc0, 0x74, 0x00, 0x00, 0x00, 0x00, /* jgne <fillme> */
2713 add_insns (buf, sizeof buf);
2714 if (offset_p)
2715 *offset_p = 18;
2716 if (size_p)
2717 *size_p = 4;
2720 /* The "emit_lt_goto" emit_ops method for s390x. */
2722 static void
2723 s390x_emit_lt_goto (int *offset_p, int *size_p)
2725 static const unsigned char buf[] = {
2726 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20, /* cg %r2, 0(%r15) */
2727 0xe3, 0x20, 0xf0, 0x08, 0x00, 0x04, /* lg %r2, 8(%r15) */
2728 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2729 0xc0, 0x24, 0x00, 0x00, 0x00, 0x00, /* jgh <fillme> */
2731 add_insns (buf, sizeof buf);
2732 if (offset_p)
2733 *offset_p = 18;
2734 if (size_p)
2735 *size_p = 4;
2738 /* The "emit_le_goto" emit_ops method for s390x. */
2740 static void
2741 s390x_emit_le_goto (int *offset_p, int *size_p)
2743 static const unsigned char buf[] = {
2744 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20, /* cg %r2, 0(%r15) */
2745 0xe3, 0x20, 0xf0, 0x08, 0x00, 0x04, /* lg %r2, 8(%r15) */
2746 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2747 0xc0, 0xa4, 0x00, 0x00, 0x00, 0x00, /* jghe <fillme> */
2749 add_insns (buf, sizeof buf);
2750 if (offset_p)
2751 *offset_p = 18;
2752 if (size_p)
2753 *size_p = 4;
2756 /* The "emit_gt_goto" emit_ops method for s390x. */
2758 static void
2759 s390x_emit_gt_goto (int *offset_p, int *size_p)
2761 static const unsigned char buf[] = {
2762 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20, /* cg %r2, 0(%r15) */
2763 0xe3, 0x20, 0xf0, 0x08, 0x00, 0x04, /* lg %r2, 8(%r15) */
2764 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2765 0xc0, 0x44, 0x00, 0x00, 0x00, 0x00, /* jgl <fillme> */
2767 add_insns (buf, sizeof buf);
2768 if (offset_p)
2769 *offset_p = 18;
2770 if (size_p)
2771 *size_p = 4;
2774 /* The "emit_ge_goto" emit_ops method for s390x. */
2776 static void
2777 s390x_emit_ge_goto (int *offset_p, int *size_p)
2779 static const unsigned char buf[] = {
2780 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20, /* cg %r2, 0(%r15) */
2781 0xe3, 0x20, 0xf0, 0x08, 0x00, 0x04, /* lg %r2, 8(%r15) */
2782 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2783 0xc0, 0xc4, 0x00, 0x00, 0x00, 0x00, /* jgle <fillme> */
2785 add_insns (buf, sizeof buf);
2786 if (offset_p)
2787 *offset_p = 18;
2788 if (size_p)
2789 *size_p = 4;
2792 /* The "emit_ops" structure for s390x. */
2794 static struct emit_ops s390x_emit_ops =
2796 s390x_emit_prologue,
2797 s390x_emit_epilogue,
2798 s390x_emit_add,
2799 s390x_emit_sub,
2800 s390x_emit_mul,
2801 s390x_emit_lsh,
2802 s390x_emit_rsh_signed,
2803 s390x_emit_rsh_unsigned,
2804 s390x_emit_ext,
2805 s390x_emit_log_not,
2806 s390x_emit_bit_and,
2807 s390x_emit_bit_or,
2808 s390x_emit_bit_xor,
2809 s390x_emit_bit_not,
2810 s390x_emit_equal,
2811 s390x_emit_less_signed,
2812 s390x_emit_less_unsigned,
2813 s390x_emit_ref,
2814 s390x_emit_if_goto,
2815 s390_emit_goto,
2816 s390_write_goto_address,
2817 s390x_emit_const,
2818 s390x_emit_call,
2819 s390x_emit_reg,
2820 s390x_emit_pop,
2821 s390x_emit_stack_flush,
2822 s390x_emit_zero_ext,
2823 s390x_emit_swap,
2824 s390x_emit_stack_adjust,
2825 s390x_emit_int_call_1,
2826 s390x_emit_void_call_2,
2827 s390x_emit_eq_goto,
2828 s390x_emit_ne_goto,
2829 s390x_emit_lt_goto,
2830 s390x_emit_le_goto,
2831 s390x_emit_gt_goto,
2832 s390x_emit_ge_goto
2834 #endif
2836 /* The "emit_ops" target ops method. */
2838 emit_ops *
2839 s390_target::emit_ops ()
2841 #ifdef __s390x__
2842 struct regcache *regcache = get_thread_regcache (current_thread, 0);
2844 if (register_size (regcache->tdesc, 0) == 8)
2845 return &s390x_emit_ops;
2846 else
2847 #endif
2848 return &s390_emit_ops_impl;
2851 /* The linux target ops object. */
2853 linux_process_target *the_linux_target = &the_s390_target;
2855 void
2856 initialize_low_arch (void)
2858 /* Initialize the Linux target descriptions. */
2860 init_registers_s390_linux32 ();
2861 init_registers_s390_linux32v1 ();
2862 init_registers_s390_linux32v2 ();
2863 init_registers_s390_linux64 ();
2864 init_registers_s390_linux64v1 ();
2865 init_registers_s390_linux64v2 ();
2866 init_registers_s390_te_linux64 ();
2867 init_registers_s390_vx_linux64 ();
2868 init_registers_s390_tevx_linux64 ();
2869 init_registers_s390_gs_linux64 ();
2870 #ifdef __s390x__
2871 init_registers_s390x_linux64 ();
2872 init_registers_s390x_linux64v1 ();
2873 init_registers_s390x_linux64v2 ();
2874 init_registers_s390x_te_linux64 ();
2875 init_registers_s390x_vx_linux64 ();
2876 init_registers_s390x_tevx_linux64 ();
2877 init_registers_s390x_gs_linux64 ();
2878 #endif
2880 initialize_regsets_info (&s390_regsets_info);
2881 initialize_regsets_info (&s390_regsets_info_3264);