Add translations for various sub-directories
[binutils-gdb.git] / gdbserver / linux-s390-low.cc
blobcd874f6d89cde1bbb81cad47662401789e620cee
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 = current_thread->id.pid ();
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 if (register_size (current_process ()->tdesc, 0) == 4)
800 res &= 0xffffffffull;
801 #endif
802 *addrp = res;
803 return 0;
807 /* Fast tracepoint support.
809 The register save area on stack is identical for all targets:
811 0x000+i*0x10: VR0-VR31
812 0x200+i*8: GR0-GR15
813 0x280+i*4: AR0-AR15
814 0x2c0: PSWM [64-bit]
815 0x2c8: PSWA [64-bit]
816 0x2d0: FPC
818 If we're on 31-bit linux, we just don't store the high parts of the GPRs.
819 Likewise, if there's no VX support, we just store the FRs into the slots
820 of low VR halves. The agent code is responsible for rearranging that
821 into regcache. */
823 /* Code sequence saving GPRs for 31-bit target with no high GPRs. There's
824 one trick used at the very beginning: since there's no way to allocate
825 stack space without destroying CC (lay instruction can do it, but it's
826 only supported on later CPUs), we take 4 different execution paths for
827 every possible value of CC, allocate stack space, save %r0, stuff the
828 CC value in %r0 (shifted to match its position in PSWM high word),
829 then branch to common path. */
831 static const unsigned char s390_ft_entry_gpr_esa[] = {
832 0xa7, 0x14, 0x00, 0x1e, /* jo .Lcc3 */
833 0xa7, 0x24, 0x00, 0x14, /* jh .Lcc2 */
834 0xa7, 0x44, 0x00, 0x0a, /* jl .Lcc1 */
835 /* CC = 0 */
836 0xa7, 0xfa, 0xfd, 0x00, /* ahi %r15, -0x300 */
837 0x50, 0x00, 0xf2, 0x04, /* st %r0, 0x204(%r15) */
838 0xa7, 0x08, 0x00, 0x00, /* lhi %r0, 0 */
839 0xa7, 0xf4, 0x00, 0x18, /* j .Lccdone */
840 /* .Lcc1: */
841 0xa7, 0xfa, 0xfd, 0x00, /* ahi %r15, -0x300 */
842 0x50, 0x00, 0xf2, 0x04, /* st %r0, 0x204(%r15) */
843 0xa7, 0x08, 0x10, 0x00, /* lhi %r0, 0x1000 */
844 0xa7, 0xf4, 0x00, 0x10, /* j .Lccdone */
845 /* .Lcc2: */
846 0xa7, 0xfa, 0xfd, 0x00, /* ahi %r15, -0x300 */
847 0x50, 0x00, 0xf2, 0x04, /* st %r0, 0x204(%r15) */
848 0xa7, 0x08, 0x20, 0x00, /* lhi %r0, 0x2000 */
849 0xa7, 0xf4, 0x00, 0x08, /* j .Lccdone */
850 /* .Lcc3: */
851 0xa7, 0xfa, 0xfd, 0x00, /* ahi %r15, -0x300 */
852 0x50, 0x00, 0xf2, 0x04, /* st %r0, 0x204(%r15) */
853 0xa7, 0x08, 0x30, 0x00, /* lhi %r0, 0x3000 */
854 /* .Lccdone: */
855 0x50, 0x10, 0xf2, 0x0c, /* st %r1, 0x20c(%r15) */
856 0x50, 0x20, 0xf2, 0x14, /* st %r2, 0x214(%r15) */
857 0x50, 0x30, 0xf2, 0x1c, /* st %r3, 0x21c(%r15) */
858 0x50, 0x40, 0xf2, 0x24, /* st %r4, 0x224(%r15) */
859 0x50, 0x50, 0xf2, 0x2c, /* st %r5, 0x22c(%r15) */
860 0x50, 0x60, 0xf2, 0x34, /* st %r6, 0x234(%r15) */
861 0x50, 0x70, 0xf2, 0x3c, /* st %r7, 0x23c(%r15) */
862 0x50, 0x80, 0xf2, 0x44, /* st %r8, 0x244(%r15) */
863 0x50, 0x90, 0xf2, 0x4c, /* st %r9, 0x24c(%r15) */
864 0x50, 0xa0, 0xf2, 0x54, /* st %r10, 0x254(%r15) */
865 0x50, 0xb0, 0xf2, 0x5c, /* st %r11, 0x25c(%r15) */
866 0x50, 0xc0, 0xf2, 0x64, /* st %r12, 0x264(%r15) */
867 0x50, 0xd0, 0xf2, 0x6c, /* st %r13, 0x26c(%r15) */
868 0x50, 0xe0, 0xf2, 0x74, /* st %r14, 0x274(%r15) */
869 /* Compute original value of %r15 and store it. We use ahi instead
870 of la to preserve the whole value, and not just the low 31 bits.
871 This is not particularly important here, but essential in the
872 zarch case where someone might be using the high word of %r15
873 as an extra register. */
874 0x18, 0x1f, /* lr %r1, %r15 */
875 0xa7, 0x1a, 0x03, 0x00, /* ahi %r1, 0x300 */
876 0x50, 0x10, 0xf2, 0x7c, /* st %r1, 0x27c(%r15) */
879 /* Code sequence saving GPRs for 31-bit target with high GPRs and for 64-bit
880 target. Same as above, except this time we can use load/store multiple,
881 since the 64-bit regs are tightly packed. */
883 static const unsigned char s390_ft_entry_gpr_zarch[] = {
884 0xa7, 0x14, 0x00, 0x21, /* jo .Lcc3 */
885 0xa7, 0x24, 0x00, 0x16, /* jh .Lcc2 */
886 0xa7, 0x44, 0x00, 0x0b, /* jl .Lcc1 */
887 /* CC = 0 */
888 0xa7, 0xfb, 0xfd, 0x00, /* aghi %r15, -0x300 */
889 0xeb, 0x0e, 0xf2, 0x00, 0x00, 0x24, /* stmg %r0, %r14, 0x200(%r15) */
890 0xa7, 0x08, 0x00, 0x00, /* lhi %r0, 0 */
891 0xa7, 0xf4, 0x00, 0x1b, /* j .Lccdone */
892 /* .Lcc1: */
893 0xa7, 0xfb, 0xfd, 0x00, /* aghi %r15, -0x300 */
894 0xeb, 0x0e, 0xf2, 0x00, 0x00, 0x24, /* stmg %r0, %r14, 0x200(%r15) */
895 0xa7, 0x08, 0x10, 0x00, /* lhi %r0, 0x1000 */
896 0xa7, 0xf4, 0x00, 0x12, /* j .Lccdone */
897 /* .Lcc2: */
898 0xa7, 0xfb, 0xfd, 0x00, /* aghi %r15, -0x300 */
899 0xeb, 0x0e, 0xf2, 0x00, 0x00, 0x24, /* stmg %r0, %r14, 0x200(%r15) */
900 0xa7, 0x08, 0x20, 0x00, /* lhi %r0, 0x2000 */
901 0xa7, 0xf4, 0x00, 0x09, /* j .Lccdone */
902 /* .Lcc3: */
903 0xa7, 0xfb, 0xfd, 0x00, /* aghi %r15, -0x300 */
904 0xeb, 0x0e, 0xf2, 0x00, 0x00, 0x24, /* stmg %r0, %r14, 0x200(%r15) */
905 0xa7, 0x08, 0x30, 0x00, /* lhi %r0, 0x3000 */
906 /* .Lccdone: */
907 0xb9, 0x04, 0x00, 0x1f, /* lgr %r1, %r15 */
908 0xa7, 0x1b, 0x03, 0x00, /* aghi %r1, 0x300 */
909 0xe3, 0x10, 0xf2, 0x78, 0x00, 0x24, /* stg %r1, 0x278(%r15) */
912 /* Code sequence saving ARs, PSWM and FPC. PSWM has to be assembled from
913 current PSWM (read by epsw) and CC from entry (in %r0). */
915 static const unsigned char s390_ft_entry_misc[] = {
916 0x9b, 0x0f, 0xf2, 0x80, /* stam %a0, %a15, 0x20(%%r15) */
917 0xb9, 0x8d, 0x00, 0x23, /* epsw %r2, %r3 */
918 0xa7, 0x18, 0xcf, 0xff, /* lhi %r1, ~0x3000 */
919 0x14, 0x21, /* nr %r2, %r1 */
920 0x16, 0x20, /* or %r2, %r0 */
921 0x50, 0x20, 0xf2, 0xc0, /* st %r2, 0x2c0(%r15) */
922 0x50, 0x30, 0xf2, 0xc4, /* st %r3, 0x2c4(%r15) */
923 0xb2, 0x9c, 0xf2, 0xd0, /* stfpc 0x2d0(%r15) */
926 /* Code sequence saving FRs, used if VX not supported. */
928 static const unsigned char s390_ft_entry_fr[] = {
929 0x60, 0x00, 0xf0, 0x00, /* std %f0, 0x000(%r15) */
930 0x60, 0x10, 0xf0, 0x10, /* std %f1, 0x010(%r15) */
931 0x60, 0x20, 0xf0, 0x20, /* std %f2, 0x020(%r15) */
932 0x60, 0x30, 0xf0, 0x30, /* std %f3, 0x030(%r15) */
933 0x60, 0x40, 0xf0, 0x40, /* std %f4, 0x040(%r15) */
934 0x60, 0x50, 0xf0, 0x50, /* std %f5, 0x050(%r15) */
935 0x60, 0x60, 0xf0, 0x60, /* std %f6, 0x060(%r15) */
936 0x60, 0x70, 0xf0, 0x70, /* std %f7, 0x070(%r15) */
937 0x60, 0x80, 0xf0, 0x80, /* std %f8, 0x080(%r15) */
938 0x60, 0x90, 0xf0, 0x90, /* std %f9, 0x090(%r15) */
939 0x60, 0xa0, 0xf0, 0xa0, /* std %f10, 0x0a0(%r15) */
940 0x60, 0xb0, 0xf0, 0xb0, /* std %f11, 0x0b0(%r15) */
941 0x60, 0xc0, 0xf0, 0xc0, /* std %f12, 0x0c0(%r15) */
942 0x60, 0xd0, 0xf0, 0xd0, /* std %f13, 0x0d0(%r15) */
943 0x60, 0xe0, 0xf0, 0xe0, /* std %f14, 0x0e0(%r15) */
944 0x60, 0xf0, 0xf0, 0xf0, /* std %f15, 0x0f0(%r15) */
947 /* Code sequence saving VRs, used if VX not supported. */
949 static const unsigned char s390_ft_entry_vr[] = {
950 0xe7, 0x0f, 0xf0, 0x00, 0x00, 0x3e, /* vstm %v0, %v15, 0x000(%r15) */
951 0xe7, 0x0f, 0xf1, 0x00, 0x0c, 0x3e, /* vstm %v16, %v31, 0x100(%r15) */
954 /* Code sequence doing the collection call for 31-bit target. %r1 contains
955 the address of the literal pool. */
957 static const unsigned char s390_ft_main_31[] = {
958 /* Load the literals into registers. */
959 0x58, 0x50, 0x10, 0x00, /* l %r5, 0x0(%r1) */
960 0x58, 0x20, 0x10, 0x04, /* l %r2, 0x4(%r1) */
961 0x58, 0x40, 0x10, 0x08, /* l %r4, 0x8(%r1) */
962 0x58, 0x60, 0x10, 0x0c, /* l %r6, 0xc(%r1) */
963 /* Save original PSWA (tracepoint address | 0x80000000). */
964 0x50, 0x50, 0xf2, 0xcc, /* st %r5, 0x2cc(%r15) */
965 /* Construct a collecting_t object at %r15+0x2e0. */
966 0x50, 0x20, 0xf2, 0xe0, /* st %r2, 0x2e0(%r15) */
967 0x9b, 0x00, 0xf2, 0xe4, /* stam %a0, %a0, 0x2e4(%r15) */
968 /* Move its address to %r0. */
969 0x41, 0x00, 0xf2, 0xe0, /* la %r0, 0x2e0(%r15) */
970 /* Take the lock. */
971 /* .Lloop: */
972 0xa7, 0x18, 0x00, 0x00, /* lhi %r1, 0 */
973 0xba, 0x10, 0x60, 0x00, /* cs %r1, %r0, 0(%r6) */
974 0xa7, 0x74, 0xff, 0xfc, /* jne .Lloop */
975 /* Address of the register save block to %r3. */
976 0x18, 0x3f, /* lr %r3, %r15 */
977 /* Make a stack frame, so that we can call the collector. */
978 0xa7, 0xfa, 0xff, 0xa0, /* ahi %r15, -0x60 */
979 /* Call it. */
980 0x0d, 0xe4, /* basr %r14, %r4 */
981 /* And get rid of the stack frame again. */
982 0x41, 0xf0, 0xf0, 0x60, /* la %r15, 0x60(%r15) */
983 /* Leave the lock. */
984 0x07, 0xf0, /* br %r0 */
985 0xa7, 0x18, 0x00, 0x00, /* lhi %r1, 0 */
986 0x50, 0x10, 0x60, 0x00, /* st %t1, 0(%r6) */
989 /* Code sequence doing the collection call for 64-bit target. %r1 contains
990 the address of the literal pool. */
992 static const unsigned char s390_ft_main_64[] = {
993 /* Load the literals into registers. */
994 0xe3, 0x50, 0x10, 0x00, 0x00, 0x04, /* lg %r5, 0x00(%r1) */
995 0xe3, 0x20, 0x10, 0x08, 0x00, 0x04, /* lg %r2, 0x08(%r1) */
996 0xe3, 0x40, 0x10, 0x10, 0x00, 0x04, /* lg %r4, 0x10(%r1) */
997 0xe3, 0x60, 0x10, 0x18, 0x00, 0x04, /* lg %r6, 0x18(%r1) */
998 /* Save original PSWA (tracepoint address). */
999 0xe3, 0x50, 0xf2, 0xc8, 0x00, 0x24, /* stg %r5, 0x2c8(%r15) */
1000 /* Construct a collecting_t object at %r15+0x2e0. */
1001 0xe3, 0x20, 0xf2, 0xe0, 0x00, 0x24, /* stg %r2, 0x2e0(%r15) */
1002 0x9b, 0x01, 0xf2, 0xe8, /* stam %a0, %a1, 0x2e8(%r15) */
1003 /* Move its address to %r0. */
1004 0x41, 0x00, 0xf2, 0xe0, /* la %r0, 0x2e0(%r15) */
1005 /* Take the lock. */
1006 /* .Lloop: */
1007 0xa7, 0x19, 0x00, 0x00, /* lghi %r1, 0 */
1008 0xeb, 0x10, 0x60, 0x00, 0x00, 0x30, /* csg %r1, %r0, 0(%r6) */
1009 0xa7, 0x74, 0xff, 0xfb, /* jne .Lloop */
1010 /* Address of the register save block to %r3. */
1011 0xb9, 0x04, 0x00, 0x3f, /* lgr %r3, %r15 */
1012 /* Make a stack frame, so that we can call the collector. */
1013 0xa7, 0xfb, 0xff, 0x60, /* aghi %r15, -0xa0 */
1014 /* Call it. */
1015 0x0d, 0xe4, /* basr %r14, %r4 */
1016 /* And get rid of the stack frame again. */
1017 0x41, 0xf0, 0xf0, 0xa0, /* la %r15, 0xa0(%r15) */
1018 /* Leave the lock. */
1019 0x07, 0xf0, /* br %r0 */
1020 0xa7, 0x19, 0x00, 0x00, /* lghi %r1, 0 */
1021 0xe3, 0x10, 0x60, 0x00, 0x00, 0x24, /* stg %t1, 0(%r6) */
1024 /* Code sequence restoring FRs, for targets with no VX support. */
1026 static const unsigned char s390_ft_exit_fr[] = {
1027 0x68, 0x00, 0xf0, 0x00, /* ld %f0, 0x000(%r15) */
1028 0x68, 0x10, 0xf0, 0x10, /* ld %f1, 0x010(%r15) */
1029 0x68, 0x20, 0xf0, 0x20, /* ld %f2, 0x020(%r15) */
1030 0x68, 0x30, 0xf0, 0x30, /* ld %f3, 0x030(%r15) */
1031 0x68, 0x40, 0xf0, 0x40, /* ld %f4, 0x040(%r15) */
1032 0x68, 0x50, 0xf0, 0x50, /* ld %f5, 0x050(%r15) */
1033 0x68, 0x60, 0xf0, 0x60, /* ld %f6, 0x060(%r15) */
1034 0x68, 0x70, 0xf0, 0x70, /* ld %f7, 0x070(%r15) */
1035 0x68, 0x80, 0xf0, 0x80, /* ld %f8, 0x080(%r15) */
1036 0x68, 0x90, 0xf0, 0x90, /* ld %f9, 0x090(%r15) */
1037 0x68, 0xa0, 0xf0, 0xa0, /* ld %f10, 0x0a0(%r15) */
1038 0x68, 0xb0, 0xf0, 0xb0, /* ld %f11, 0x0b0(%r15) */
1039 0x68, 0xc0, 0xf0, 0xc0, /* ld %f12, 0x0c0(%r15) */
1040 0x68, 0xd0, 0xf0, 0xd0, /* ld %f13, 0x0d0(%r15) */
1041 0x68, 0xe0, 0xf0, 0xe0, /* ld %f14, 0x0e0(%r15) */
1042 0x68, 0xf0, 0xf0, 0xf0, /* ld %f15, 0x0f0(%r15) */
1045 /* Code sequence restoring VRs. */
1047 static const unsigned char s390_ft_exit_vr[] = {
1048 0xe7, 0x0f, 0xf0, 0x00, 0x00, 0x36, /* vlm %v0, %v15, 0x000(%r15) */
1049 0xe7, 0x0f, 0xf1, 0x00, 0x0c, 0x36, /* vlm %v16, %v31, 0x100(%r15) */
1052 /* Code sequence restoring misc registers. As for PSWM, only CC should be
1053 modified by C code, so we use the alr instruction to restore it by
1054 manufacturing an operand that'll result in the original flags. */
1056 static const unsigned char s390_ft_exit_misc[] = {
1057 0xb2, 0x9d, 0xf2, 0xd0, /* lfpc 0x2d0(%r15) */
1058 0x58, 0x00, 0xf2, 0xc0, /* l %r0, 0x2c0(%r15) */
1059 /* Extract CC to high 2 bits of %r0. */
1060 0x88, 0x00, 0x00, 0x0c, /* srl %r0, 12 */
1061 0x89, 0x00, 0x00, 0x1e, /* sll %r0, 30 */
1062 /* Add %r0 to itself. Result will be nonzero iff CC bit 0 is set, and
1063 will have carry iff CC bit 1 is set - resulting in the same flags
1064 as the original. */
1065 0x1e, 0x00, /* alr %r0, %r0 */
1066 0x9a, 0x0f, 0xf2, 0x80, /* lam %a0, %a15, 0x280(%r15) */
1069 /* Code sequence restoring GPRs, for 31-bit targets with no high GPRs. */
1071 static const unsigned char s390_ft_exit_gpr_esa[] = {
1072 0x58, 0x00, 0xf2, 0x04, /* l %r0, 0x204(%r15) */
1073 0x58, 0x10, 0xf2, 0x0c, /* l %r1, 0x20c(%r15) */
1074 0x58, 0x20, 0xf2, 0x14, /* l %r2, 0x214(%r15) */
1075 0x58, 0x30, 0xf2, 0x1c, /* l %r3, 0x21c(%r15) */
1076 0x58, 0x40, 0xf2, 0x24, /* l %r4, 0x224(%r15) */
1077 0x58, 0x50, 0xf2, 0x2c, /* l %r5, 0x22c(%r15) */
1078 0x58, 0x60, 0xf2, 0x34, /* l %r6, 0x234(%r15) */
1079 0x58, 0x70, 0xf2, 0x3c, /* l %r7, 0x23c(%r15) */
1080 0x58, 0x80, 0xf2, 0x44, /* l %r8, 0x244(%r15) */
1081 0x58, 0x90, 0xf2, 0x4c, /* l %r9, 0x24c(%r15) */
1082 0x58, 0xa0, 0xf2, 0x54, /* l %r10, 0x254(%r15) */
1083 0x58, 0xb0, 0xf2, 0x5c, /* l %r11, 0x25c(%r15) */
1084 0x58, 0xc0, 0xf2, 0x64, /* l %r12, 0x264(%r15) */
1085 0x58, 0xd0, 0xf2, 0x6c, /* l %r13, 0x26c(%r15) */
1086 0x58, 0xe0, 0xf2, 0x74, /* l %r14, 0x274(%r15) */
1087 0x58, 0xf0, 0xf2, 0x7c, /* l %r15, 0x27c(%r15) */
1090 /* Code sequence restoring GPRs, for 64-bit targets and 31-bit targets
1091 with high GPRs. */
1093 static const unsigned char s390_ft_exit_gpr_zarch[] = {
1094 0xeb, 0x0f, 0xf2, 0x00, 0x00, 0x04, /* lmg %r0, %r15, 0x200(%r15) */
1097 /* Writes instructions to target, updating the to pointer. */
1099 static void
1100 append_insns (CORE_ADDR *to, size_t len, const unsigned char *buf)
1102 target_write_memory (*to, buf, len);
1103 *to += len;
1106 /* Relocates an instruction from oldloc to *to, updating to. */
1108 static int
1109 s390_relocate_instruction (CORE_ADDR *to, CORE_ADDR oldloc, int is_64)
1111 gdb_byte buf[6];
1112 int ilen;
1113 int op2;
1114 /* 0: no fixup, 1: PC16DBL fixup, 2: PC32DBL fixup. */
1115 int mode = 0;
1116 int is_bras = 0;
1117 read_inferior_memory (oldloc, buf, sizeof buf);
1118 if (buf[0] < 0x40)
1119 ilen = 2;
1120 else if (buf[0] < 0xc0)
1121 ilen = 4;
1122 else
1123 ilen = 6;
1124 switch (buf[0])
1126 case 0x05: /* BALR */
1127 case 0x0c: /* BASSM */
1128 case 0x0d: /* BASR */
1129 case 0x45: /* BAL */
1130 case 0x4d: /* BAS */
1131 /* These save a return address and mess around with registers.
1132 We can't relocate them. */
1133 return 1;
1134 case 0x84: /* BRXH */
1135 case 0x85: /* BRXLE */
1136 mode = 1;
1137 break;
1138 case 0xa7:
1139 op2 = buf[1] & 0xf;
1140 /* BRC, BRAS, BRCT, BRCTG */
1141 if (op2 >= 4 && op2 <= 7)
1142 mode = 1;
1143 /* BRAS */
1144 if (op2 == 5)
1145 is_bras = 1;
1146 break;
1147 case 0xc0:
1148 op2 = buf[1] & 0xf;
1149 /* LARL, BRCL, BRASL */
1150 if (op2 == 0 || op2 == 4 || op2 == 5)
1151 mode = 2;
1152 /* BRASL */
1153 if (op2 == 5)
1154 is_bras = 1;
1155 break;
1156 case 0xc4:
1157 case 0xc6:
1158 /* PC-relative addressing instructions. */
1159 mode = 2;
1160 break;
1161 case 0xc5: /* BPRP */
1162 case 0xc7: /* BPP */
1163 /* Branch prediction - just skip it. */
1164 return 0;
1165 case 0xcc:
1166 op2 = buf[1] & 0xf;
1167 /* BRCTH */
1168 if (op2 == 6)
1169 mode = 2;
1170 break;
1171 case 0xec:
1172 op2 = buf[5];
1173 switch (op2)
1175 case 0x44: /* BRXHG */
1176 case 0x45: /* BRXLG */
1177 case 0x64: /* CGRJ */
1178 case 0x65: /* CLGRJ */
1179 case 0x76: /* CRJ */
1180 case 0x77: /* CLRJ */
1181 mode = 1;
1182 break;
1184 break;
1187 if (mode != 0)
1189 /* We'll have to relocate an instruction with a PC-relative field.
1190 First, compute the target. */
1191 int64_t loffset = 0;
1192 CORE_ADDR target;
1193 if (mode == 1)
1195 int16_t soffset = 0;
1196 memcpy (&soffset, buf + 2, 2);
1197 loffset = soffset;
1199 else if (mode == 2)
1201 int32_t soffset = 0;
1202 memcpy (&soffset, buf + 2, 4);
1203 loffset = soffset;
1205 target = oldloc + loffset * 2;
1206 if (!is_64)
1207 target &= 0x7fffffff;
1209 if (is_bras)
1211 /* BRAS or BRASL was used. We cannot just relocate those, since
1212 they save the return address in a register. We can, however,
1213 replace them with a LARL+JG sequence. */
1215 /* Make the LARL. */
1216 int32_t soffset;
1217 buf[0] = 0xc0;
1218 buf[1] &= 0xf0;
1219 loffset = oldloc + ilen - *to;
1220 loffset >>= 1;
1221 soffset = loffset;
1222 if (soffset != loffset && is_64)
1223 return 1;
1224 memcpy (buf + 2, &soffset, 4);
1225 append_insns (to, 6, buf);
1227 /* Note: this is not fully correct. In 31-bit mode, LARL will write
1228 an address with the top bit 0, while BRAS/BRASL will write it
1229 with top bit 1. It should not matter much, since linux compilers
1230 use BR and not BSM to return from functions, but it could confuse
1231 some poor stack unwinder. */
1233 /* We'll now be writing a JG. */
1234 mode = 2;
1235 buf[0] = 0xc0;
1236 buf[1] = 0xf4;
1237 ilen = 6;
1240 /* Compute the new offset and write it to the buffer. */
1241 loffset = target - *to;
1242 loffset >>= 1;
1244 if (mode == 1)
1246 int16_t soffset = loffset;
1247 if (soffset != loffset)
1248 return 1;
1249 memcpy (buf + 2, &soffset, 2);
1251 else if (mode == 2)
1253 int32_t soffset = loffset;
1254 if (soffset != loffset && is_64)
1255 return 1;
1256 memcpy (buf + 2, &soffset, 4);
1259 append_insns (to, ilen, buf);
1260 return 0;
1263 bool
1264 s390_target::supports_fast_tracepoints ()
1266 return true;
1269 /* Implementation of target ops method
1270 "install_fast_tracepoint_jump_pad". */
1273 s390_target::install_fast_tracepoint_jump_pad
1274 (CORE_ADDR tpoint, CORE_ADDR tpaddr, CORE_ADDR collector,
1275 CORE_ADDR lockaddr, ULONGEST orig_size, CORE_ADDR *jump_entry,
1276 CORE_ADDR *trampoline, ULONGEST *trampoline_size,
1277 unsigned char *jjump_pad_insn, ULONGEST *jjump_pad_insn_size,
1278 CORE_ADDR *adjusted_insn_addr, CORE_ADDR *adjusted_insn_addr_end,
1279 char *err)
1281 int i;
1282 int64_t loffset;
1283 int32_t offset;
1284 unsigned char jbuf[6] = { 0xc0, 0xf4, 0, 0, 0, 0 }; /* jg ... */
1285 CORE_ADDR buildaddr = *jump_entry;
1286 #ifdef __s390x__
1287 int is_64 = register_size (current_process ()->tdesc, 0) == 8;
1288 int is_zarch = is_64 || have_hwcap_s390_high_gprs;
1289 int has_vx = have_hwcap_s390_vx;
1290 #else
1291 int is_64 = 0, is_zarch = 0, has_vx = 0;
1292 #endif
1293 CORE_ADDR literals[4] = {
1294 tpaddr,
1295 tpoint,
1296 collector,
1297 lockaddr,
1300 /* First, store the GPRs. */
1301 if (is_zarch)
1302 append_insns (&buildaddr, sizeof s390_ft_entry_gpr_zarch,
1303 s390_ft_entry_gpr_zarch);
1304 else
1305 append_insns (&buildaddr, sizeof s390_ft_entry_gpr_esa,
1306 s390_ft_entry_gpr_esa);
1308 /* Second, misc registers (ARs, PSWM, FPC). PSWA will be stored below. */
1309 append_insns (&buildaddr, sizeof s390_ft_entry_misc, s390_ft_entry_misc);
1311 /* Third, FRs or VRs. */
1312 if (has_vx)
1313 append_insns (&buildaddr, sizeof s390_ft_entry_vr, s390_ft_entry_vr);
1314 else
1315 append_insns (&buildaddr, sizeof s390_ft_entry_fr, s390_ft_entry_fr);
1317 /* Now, the main part of code - store PSWA, take lock, call collector,
1318 leave lock. First, we'll need to fetch 4 literals. */
1319 if (is_64) {
1320 unsigned char buf[] = {
1321 0x07, 0x07, /* nopr %r7 */
1322 0x07, 0x07, /* nopr %r7 */
1323 0x07, 0x07, /* nopr %r7 */
1324 0xa7, 0x15, 0x00, 0x12, /* bras %r1, .Lend */
1325 0, 0, 0, 0, 0, 0, 0, 0, /* tpaddr */
1326 0, 0, 0, 0, 0, 0, 0, 0, /* tpoint */
1327 0, 0, 0, 0, 0, 0, 0, 0, /* collector */
1328 0, 0, 0, 0, 0, 0, 0, 0, /* lockaddr */
1329 /* .Lend: */
1331 /* Find the proper start place in buf, so that literals will be
1332 aligned. */
1333 int bufpos = (buildaddr + 2) & 7;
1334 /* Stuff the literals into the buffer. */
1335 for (i = 0; i < 4; i++) {
1336 uint64_t lit = literals[i];
1337 memcpy (&buf[sizeof buf - 32 + i * 8], &lit, 8);
1339 append_insns (&buildaddr, sizeof buf - bufpos, buf + bufpos);
1340 append_insns (&buildaddr, sizeof s390_ft_main_64, s390_ft_main_64);
1341 } else {
1342 unsigned char buf[] = {
1343 0x07, 0x07, /* nopr %r7 */
1344 0xa7, 0x15, 0x00, 0x0a, /* bras %r1, .Lend */
1345 0, 0, 0, 0, /* tpaddr */
1346 0, 0, 0, 0, /* tpoint */
1347 0, 0, 0, 0, /* collector */
1348 0, 0, 0, 0, /* lockaddr */
1349 /* .Lend: */
1351 /* Find the proper start place in buf, so that literals will be
1352 aligned. */
1353 int bufpos = (buildaddr + 2) & 3;
1354 /* First literal will be saved as the PSWA, make sure it has the high bit
1355 set. */
1356 literals[0] |= 0x80000000;
1357 /* Stuff the literals into the buffer. */
1358 for (i = 0; i < 4; i++) {
1359 uint32_t lit = literals[i];
1360 memcpy (&buf[sizeof buf - 16 + i * 4], &lit, 4);
1362 append_insns (&buildaddr, sizeof buf - bufpos, buf + bufpos);
1363 append_insns (&buildaddr, sizeof s390_ft_main_31, s390_ft_main_31);
1366 /* Restore FRs or VRs. */
1367 if (has_vx)
1368 append_insns (&buildaddr, sizeof s390_ft_exit_vr, s390_ft_exit_vr);
1369 else
1370 append_insns (&buildaddr, sizeof s390_ft_exit_fr, s390_ft_exit_fr);
1372 /* Restore misc registers. */
1373 append_insns (&buildaddr, sizeof s390_ft_exit_misc, s390_ft_exit_misc);
1375 /* Restore the GPRs. */
1376 if (is_zarch)
1377 append_insns (&buildaddr, sizeof s390_ft_exit_gpr_zarch,
1378 s390_ft_exit_gpr_zarch);
1379 else
1380 append_insns (&buildaddr, sizeof s390_ft_exit_gpr_esa,
1381 s390_ft_exit_gpr_esa);
1383 /* Now, adjust the original instruction to execute in the jump
1384 pad. */
1385 *adjusted_insn_addr = buildaddr;
1386 if (s390_relocate_instruction (&buildaddr, tpaddr, is_64))
1388 sprintf (err, "E.Could not relocate instruction for tracepoint.");
1389 return 1;
1391 *adjusted_insn_addr_end = buildaddr;
1393 /* Finally, write a jump back to the program. */
1395 loffset = (tpaddr + orig_size) - buildaddr;
1396 loffset >>= 1;
1397 offset = loffset;
1398 if (is_64 && offset != loffset)
1400 sprintf (err,
1401 "E.Jump back from jump pad too far from tracepoint "
1402 "(offset 0x%" PRIx64 " > int33).", loffset);
1403 return 1;
1405 memcpy (jbuf + 2, &offset, 4);
1406 append_insns (&buildaddr, sizeof jbuf, jbuf);
1408 /* The jump pad is now built. Wire in a jump to our jump pad. This
1409 is always done last (by our caller actually), so that we can
1410 install fast tracepoints with threads running. This relies on
1411 the agent's atomic write support. */
1412 loffset = *jump_entry - tpaddr;
1413 loffset >>= 1;
1414 offset = loffset;
1415 if (is_64 && offset != loffset)
1417 sprintf (err,
1418 "E.Jump back from jump pad too far from tracepoint "
1419 "(offset 0x%" PRIx64 " > int33).", loffset);
1420 return 1;
1422 memcpy (jbuf + 2, &offset, 4);
1423 memcpy (jjump_pad_insn, jbuf, sizeof jbuf);
1424 *jjump_pad_insn_size = sizeof jbuf;
1426 /* Return the end address of our pad. */
1427 *jump_entry = buildaddr;
1429 return 0;
1432 /* Implementation of target ops method
1433 "get_min_fast_tracepoint_insn_len". */
1436 s390_target::get_min_fast_tracepoint_insn_len ()
1438 /* We only support using 6-byte jumps to reach the tracepoint code.
1439 If the tracepoint buffer were allocated sufficiently close (64kiB)
1440 to the executable code, and the traced instruction itself was close
1441 enough to the beginning, we could use 4-byte jumps, but this doesn't
1442 seem to be worth the effort. */
1443 return 6;
1446 /* Implementation of target ops method "get_ipa_tdesc_idx". */
1449 s390_target::get_ipa_tdesc_idx ()
1451 const target_desc *tdesc = current_process ()->tdesc;
1453 #ifdef __s390x__
1454 if (tdesc == tdesc_s390x_linux64)
1455 return S390_TDESC_64;
1456 if (tdesc == tdesc_s390x_linux64v1)
1457 return S390_TDESC_64V1;
1458 if (tdesc == tdesc_s390x_linux64v2)
1459 return S390_TDESC_64V2;
1460 if (tdesc == tdesc_s390x_te_linux64)
1461 return S390_TDESC_TE;
1462 if (tdesc == tdesc_s390x_vx_linux64)
1463 return S390_TDESC_VX;
1464 if (tdesc == tdesc_s390x_tevx_linux64)
1465 return S390_TDESC_TEVX;
1466 if (tdesc == tdesc_s390x_gs_linux64)
1467 return S390_TDESC_GS;
1468 #endif
1470 if (tdesc == tdesc_s390_linux32)
1471 return S390_TDESC_32;
1472 if (tdesc == tdesc_s390_linux32v1)
1473 return S390_TDESC_32V1;
1474 if (tdesc == tdesc_s390_linux32v2)
1475 return S390_TDESC_32V2;
1476 if (tdesc == tdesc_s390_linux64)
1477 return S390_TDESC_64;
1478 if (tdesc == tdesc_s390_linux64v1)
1479 return S390_TDESC_64V1;
1480 if (tdesc == tdesc_s390_linux64v2)
1481 return S390_TDESC_64V2;
1482 if (tdesc == tdesc_s390_te_linux64)
1483 return S390_TDESC_TE;
1484 if (tdesc == tdesc_s390_vx_linux64)
1485 return S390_TDESC_VX;
1486 if (tdesc == tdesc_s390_tevx_linux64)
1487 return S390_TDESC_TEVX;
1488 if (tdesc == tdesc_s390_gs_linux64)
1489 return S390_TDESC_GS;
1491 return 0;
1494 /* Appends given buffer to current_insn_ptr in the target. */
1496 static void
1497 add_insns (const unsigned char *start, int len)
1499 CORE_ADDR buildaddr = current_insn_ptr;
1501 threads_debug_printf ("Adding %d bytes of insn at %s",
1502 len, paddress (buildaddr));
1504 append_insns (&buildaddr, len, start);
1505 current_insn_ptr = buildaddr;
1508 /* Register usage in emit:
1510 - %r0, %r1: temp
1511 - %r2: top of stack (high word for 31-bit)
1512 - %r3: low word of top of stack (for 31-bit)
1513 - %r4, %r5: temp
1514 - %r6, %r7, %r8: don't use
1515 - %r9: saved arg1
1516 - %r10: saved arg2
1517 - %r11: frame pointer
1518 - %r12: saved top of stack for void_call_2 (high word for 31-bit)
1519 - %r13: low word of saved top of stack (for 31-bit)
1520 - %r14: return address for calls
1521 - %r15: stack pointer
1525 /* The "emit_prologue" emit_ops method for s390. */
1527 static void
1528 s390_emit_prologue (void)
1530 static const unsigned char buf[] = {
1531 0x90, 0x9f, 0xf0, 0x24, /* stm %r9, %r15, 0x24(%r15) */
1532 0x18, 0x92, /* lr %r9, %r2 */
1533 0x18, 0xa3, /* lr %r10, %r3 */
1534 0x18, 0xbf, /* lr %r11, %r15 */
1536 add_insns (buf, sizeof buf);
1539 /* The "emit_epilogue" emit_ops method for s390. */
1541 static void
1542 s390_emit_epilogue (void)
1544 static const unsigned char buf[] = {
1545 0x90, 0x23, 0xa0, 0x00, /* stm %r2, %r3, 0(%r10) */
1546 0xa7, 0x28, 0x00, 0x00, /* lhi %r2, 0 */
1547 0x98, 0x9f, 0xb0, 0x24, /* lm %r9, %r15, 0x24(%r11) */
1548 0x07, 0xfe, /* br %r14 */
1550 add_insns (buf, sizeof buf);
1553 /* The "emit_add" emit_ops method for s390. */
1555 static void
1556 s390_emit_add (void)
1558 static const unsigned char buf[] = {
1559 0x5e, 0x30, 0xf0, 0x04, /* al %r3, 4(%r15) */
1560 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x98, /* al %r2, 0(%r15) */
1561 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1563 add_insns (buf, sizeof buf);
1566 /* The "emit_sub" emit_ops method for s390. */
1568 static void
1569 s390_emit_sub (void)
1571 static const unsigned char buf[] = {
1572 0x98, 0x45, 0xf0, 0x00, /* lm %r4, %r5, 0(%r15) */
1573 0x1f, 0x53, /* slr %r5, %r3 */
1574 0xb9, 0x99, 0x00, 0x42, /* slbr %r4, %r2 */
1575 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1576 0x18, 0x35, /* lr %r3, %r5 */
1577 0x18, 0x24, /* lr %r2, %r4 */
1579 add_insns (buf, sizeof buf);
1582 /* The "emit_mul" emit_ops method for s390. */
1584 static void
1585 s390_emit_mul (void)
1587 emit_error = 1;
1590 /* The "emit_lsh" emit_ops method for s390. */
1592 static void
1593 s390_emit_lsh (void)
1595 static const unsigned char buf[] = {
1596 0x18, 0x43, /* lr %r4, %r3 */
1597 0x98, 0x23, 0xf0, 0x00, /* lm %r2, %r3, 0(%r15) */
1598 0x8d, 0x20, 0x40, 0x00, /* sldl %r2, 0(%r4) */
1599 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1601 add_insns (buf, sizeof buf);
1604 /* The "emit_rsh_signed" emit_ops method for s390. */
1606 static void
1607 s390_emit_rsh_signed (void)
1609 static const unsigned char buf[] = {
1610 0x18, 0x43, /* lr %r4, %r3 */
1611 0x98, 0x23, 0xf0, 0x00, /* lm %r2, %r3, 0(%r15) */
1612 0x8e, 0x20, 0x40, 0x00, /* srda %r2, 0(%r4) */
1613 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1615 add_insns (buf, sizeof buf);
1618 /* The "emit_rsh_unsigned" emit_ops method for s390. */
1620 static void
1621 s390_emit_rsh_unsigned (void)
1623 static const unsigned char buf[] = {
1624 0x18, 0x43, /* lr %r4, %r3 */
1625 0x98, 0x23, 0xf0, 0x00, /* lm %r2, %r3, 0(%r15) */
1626 0x8c, 0x20, 0x40, 0x00, /* srdl %r2, 0(%r4) */
1627 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1629 add_insns (buf, sizeof buf);
1632 /* The "emit_ext" emit_ops method for s390. */
1634 static void
1635 s390_emit_ext (int arg)
1637 unsigned char buf[] = {
1638 0x8d, 0x20, 0x00, (unsigned char) (64 - arg), /* sldl %r2, <64-arg> */
1639 0x8e, 0x20, 0x00, (unsigned char) (64 - arg), /* srda %r2, <64-arg> */
1641 add_insns (buf, sizeof buf);
1644 /* The "emit_log_not" emit_ops method for s390. */
1646 static void
1647 s390_emit_log_not (void)
1649 static const unsigned char buf[] = {
1650 0x16, 0x23, /* or %r2, %r3 */
1651 0xa7, 0x28, 0x00, 0x00, /* lhi %r2, 0 */
1652 0xa7, 0x38, 0x00, 0x00, /* lhi %r3, 0 */
1653 0xa7, 0x74, 0x00, 0x04, /* jne .Lskip */
1654 0xa7, 0x38, 0x00, 0x01, /* lhi %r3, 1 */
1655 /* .Lskip: */
1657 add_insns (buf, sizeof buf);
1660 /* The "emit_bit_and" emit_ops method for s390. */
1662 static void
1663 s390_emit_bit_and (void)
1665 static const unsigned char buf[] = {
1666 0x54, 0x20, 0xf0, 0x00, /* n %r2, 0(%r15) */
1667 0x54, 0x30, 0xf0, 0x04, /* n %r3, 4(%r15) */
1668 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1670 add_insns (buf, sizeof buf);
1673 /* The "emit_bit_or" emit_ops method for s390. */
1675 static void
1676 s390_emit_bit_or (void)
1678 static const unsigned char buf[] = {
1679 0x56, 0x20, 0xf0, 0x00, /* o %r2, 0(%r15) */
1680 0x56, 0x30, 0xf0, 0x04, /* o %r3, 4(%r15) */
1681 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1683 add_insns (buf, sizeof buf);
1686 /* The "emit_bit_xor" emit_ops method for s390. */
1688 static void
1689 s390_emit_bit_xor (void)
1691 static const unsigned char buf[] = {
1692 0x57, 0x20, 0xf0, 0x00, /* x %r2, 0(%r15) */
1693 0x57, 0x30, 0xf0, 0x04, /* x %r3, 4(%r15) */
1694 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1696 add_insns (buf, sizeof buf);
1699 /* The "emit_bit_not" emit_ops method for s390. */
1701 static void
1702 s390_emit_bit_not (void)
1704 static const unsigned char buf[] = {
1705 0xa7, 0x48, 0xff, 0xff, /* lhi %r4, -1 */
1706 0x17, 0x24, /* xr %r2, %r4 */
1707 0x17, 0x34, /* xr %r3, %r4 */
1709 add_insns (buf, sizeof buf);
1712 /* The "emit_equal" emit_ops method for s390. */
1714 static void
1715 s390_emit_equal (void)
1717 s390_emit_bit_xor ();
1718 s390_emit_log_not ();
1721 /* The "emit_less_signed" emit_ops method for s390. */
1723 static void
1724 s390_emit_less_signed (void)
1726 static const unsigned char buf[] = {
1727 0x59, 0x20, 0xf0, 0x00, /* c %r2, 0(%r15) */
1728 0xa7, 0x24, 0x00, 0x0c, /* jh .Lless */
1729 0xa7, 0x44, 0x00, 0x06, /* jl .Lhigh */
1730 0x55, 0x30, 0xf0, 0x04, /* cl %r3, 4(%r15) */
1731 0xa7, 0x24, 0x00, 0x06, /* jh .Lless */
1732 /* .Lhigh: */
1733 0xa7, 0x38, 0x00, 0x00, /* lhi %r3, 0 */
1734 0xa7, 0xf4, 0x00, 0x04, /* j .Lend */
1735 /* .Lless: */
1736 0xa7, 0x38, 0x00, 0x01, /* lhi %r3, 1 */
1737 /* .Lend: */
1738 0xa7, 0x28, 0x00, 0x00, /* lhi %r2, 0 */
1739 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1741 add_insns (buf, sizeof buf);
1744 /* The "emit_less_unsigned" emit_ops method for s390. */
1746 static void
1747 s390_emit_less_unsigned (void)
1749 static const unsigned char buf[] = {
1750 0x55, 0x20, 0xf0, 0x00, /* cl %r2, 0(%r15) */
1751 0xa7, 0x24, 0x00, 0x0c, /* jh .Lless */
1752 0xa7, 0x44, 0x00, 0x06, /* jl .Lhigh */
1753 0x55, 0x30, 0xf0, 0x04, /* cl %r3, 4(%r15) */
1754 0xa7, 0x24, 0x00, 0x06, /* jh .Lless */
1755 /* .Lhigh: */
1756 0xa7, 0x38, 0x00, 0x00, /* lhi %r3, 0 */
1757 0xa7, 0xf4, 0x00, 0x04, /* j .Lend */
1758 /* .Lless: */
1759 0xa7, 0x38, 0x00, 0x01, /* lhi %r3, 1 */
1760 /* .Lend: */
1761 0xa7, 0x28, 0x00, 0x00, /* lhi %r2, 0 */
1762 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1764 add_insns (buf, sizeof buf);
1767 /* The "emit_ref" emit_ops method for s390. */
1769 static void
1770 s390_emit_ref (int size)
1772 static const unsigned char buf1[] = {
1773 0xa7, 0x28, 0x00, 0x00, /* lhi %r2, 0 */
1774 0x43, 0x30, 0x30, 0x00, /* ic %r3, 0(%r3) */
1776 static const unsigned char buf2[] = {
1777 0xa7, 0x28, 0x00, 0x00, /* lhi %r2, 0 */
1778 0x48, 0x30, 0x30, 0x00, /* lh %r3, 0(%r3) */
1780 static const unsigned char buf4[] = {
1781 0xa7, 0x28, 0x00, 0x00, /* lhi %r2, 0 */
1782 0x58, 0x30, 0x30, 0x00, /* l %r3, 0(%r3) */
1784 static const unsigned char buf8[] = {
1785 0x98, 0x23, 0x30, 0x00, /* lm %r2, %r3, 0(%r3) */
1787 switch (size)
1789 case 1:
1790 add_insns (buf1, sizeof buf1);
1791 break;
1792 case 2:
1793 add_insns (buf2, sizeof buf2);
1794 break;
1795 case 4:
1796 add_insns (buf4, sizeof buf4);
1797 break;
1798 case 8:
1799 add_insns (buf8, sizeof buf8);
1800 break;
1801 default:
1802 emit_error = 1;
1806 /* The "emit_if_goto" emit_ops method for s390. */
1808 static void
1809 s390_emit_if_goto (int *offset_p, int *size_p)
1811 static const unsigned char buf[] = {
1812 0x16, 0x23, /* or %r2, %r3 */
1813 0x98, 0x23, 0xf0, 0x00, /* lm %r2, %r3, 0(%r15) */
1814 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1815 0xc0, 0x74, 0x00, 0x00, 0x00, 0x00 /* jgne <fillme> */
1817 add_insns (buf, sizeof buf);
1818 if (offset_p)
1819 *offset_p = 12;
1820 if (size_p)
1821 *size_p = 4;
1824 /* The "emit_goto" emit_ops method for s390 and s390x. */
1826 static void
1827 s390_emit_goto (int *offset_p, int *size_p)
1829 static const unsigned char buf[] = {
1830 0xc0, 0xf4, 0x00, 0x00, 0x00, 0x00, /* jg <fillme> */
1832 add_insns (buf, sizeof buf);
1833 if (offset_p)
1834 *offset_p = 2;
1835 if (size_p)
1836 *size_p = 4;
1839 /* The "write_goto_address" emit_ops method for s390 and s390x. */
1841 static void
1842 s390_write_goto_address (CORE_ADDR from, CORE_ADDR to, int size)
1844 long diff = ((long) (to - (from - 2))) / 2;
1845 int sdiff = diff;
1846 unsigned char buf[sizeof sdiff];
1848 /* We're only doing 4-byte sizes at the moment. */
1849 if (size != sizeof sdiff || sdiff != diff)
1851 emit_error = 1;
1852 return;
1855 memcpy (buf, &sdiff, sizeof sdiff);
1856 target_write_memory (from, buf, sizeof sdiff);
1859 /* Preparation for emitting a literal pool of given size. Loads the address
1860 of the pool into %r1, and jumps over it. Called should emit the pool data
1861 immediately afterwards. Used for both s390 and s390x. */
1863 static void
1864 s390_emit_litpool (int size)
1866 static const unsigned char nop[] = {
1867 0x07, 0x07,
1869 unsigned char buf[] = {
1870 0xa7, 0x15, 0x00,
1871 (unsigned char) ((size + 4) / 2), /* bras %r1, .Lend+size */
1872 /* .Lend: */
1874 if (size == 4)
1876 /* buf needs to start at even halfword for litpool to be aligned */
1877 if (current_insn_ptr & 2)
1878 add_insns (nop, sizeof nop);
1880 else
1882 while ((current_insn_ptr & 6) != 4)
1883 add_insns (nop, sizeof nop);
1885 add_insns (buf, sizeof buf);
1888 /* The "emit_const" emit_ops method for s390. */
1890 static void
1891 s390_emit_const (LONGEST num)
1893 unsigned long long n = num;
1894 unsigned char buf_s[] = {
1895 /* lhi %r3, <num> */
1896 0xa7, 0x38,
1897 (unsigned char) (num >> 8), (unsigned char) num,
1898 /* xr %r2, %r2 */
1899 0x17, 0x22,
1901 static const unsigned char buf_l[] = {
1902 0x98, 0x23, 0x10, 0x00, /* lm %r2, %r3, 0(%r1) */
1904 if (num < 0x8000 && num >= 0)
1905 add_insns (buf_s, sizeof buf_s);
1906 else
1908 s390_emit_litpool (8);
1909 add_insns ((unsigned char *) &n, sizeof n);
1910 add_insns (buf_l, sizeof buf_l);
1914 /* The "emit_call" emit_ops method for s390. */
1916 static void
1917 s390_emit_call (CORE_ADDR fn)
1919 unsigned int n = fn;
1920 static const unsigned char buf[] = {
1921 0x58, 0x10, 0x10, 0x00, /* l %r1, 0(%r1) */
1922 0xa7, 0xfa, 0xff, 0xa0, /* ahi %r15, -0x60 */
1923 0x0d, 0xe1, /* basr %r14, %r1 */
1924 0xa7, 0xfa, 0x00, 0x60, /* ahi %r15, 0x60 */
1926 s390_emit_litpool (4);
1927 add_insns ((unsigned char *) &n, sizeof n);
1928 add_insns (buf, sizeof buf);
1931 /* The "emit_reg" emit_ops method for s390. */
1933 static void
1934 s390_emit_reg (int reg)
1936 unsigned char bufpre[] = {
1937 /* lr %r2, %r9 */
1938 0x18, 0x29,
1939 /* lhi %r3, <reg> */
1940 0xa7, 0x38, (unsigned char) (reg >> 8), (unsigned char) reg,
1942 add_insns (bufpre, sizeof bufpre);
1943 s390_emit_call (get_raw_reg_func_addr ());
1946 /* The "emit_pop" emit_ops method for s390. */
1948 static void
1949 s390_emit_pop (void)
1951 static const unsigned char buf[] = {
1952 0x98, 0x23, 0xf0, 0x00, /* lm %r2, %r3, 0(%r15) */
1953 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1955 add_insns (buf, sizeof buf);
1958 /* The "emit_stack_flush" emit_ops method for s390. */
1960 static void
1961 s390_emit_stack_flush (void)
1963 static const unsigned char buf[] = {
1964 0xa7, 0xfa, 0xff, 0xf8, /* ahi %r15, -8 */
1965 0x90, 0x23, 0xf0, 0x00, /* stm %r2, %r3, 0(%r15) */
1967 add_insns (buf, sizeof buf);
1970 /* The "emit_zero_ext" emit_ops method for s390. */
1972 static void
1973 s390_emit_zero_ext (int arg)
1975 unsigned char buf[] = {
1976 0x8d, 0x20, 0x00, (unsigned char) (64 - arg), /* sldl %r2, <64-arg> */
1977 0x8c, 0x20, 0x00, (unsigned char) (64 - arg), /* srdl %r2, <64-arg> */
1979 add_insns (buf, sizeof buf);
1982 /* The "emit_swap" emit_ops method for s390. */
1984 static void
1985 s390_emit_swap (void)
1987 static const unsigned char buf[] = {
1988 0x98, 0x45, 0xf0, 0x00, /* lm %r4, %r5, 0(%r15) */
1989 0x90, 0x23, 0xf0, 0x00, /* stm %r2, %r3, 0(%r15) */
1990 0x18, 0x24, /* lr %r2, %r4 */
1991 0x18, 0x35, /* lr %r3, %r5 */
1993 add_insns (buf, sizeof buf);
1996 /* The "emit_stack_adjust" emit_ops method for s390. */
1998 static void
1999 s390_emit_stack_adjust (int n)
2001 unsigned char buf[] = {
2002 /* ahi %r15, 8*n */
2003 0xa7, 0xfa,
2004 (unsigned char ) (n * 8 >> 8), (unsigned char) (n * 8),
2006 add_insns (buf, sizeof buf);
2009 /* Sets %r2 to a 32-bit constant. */
2011 static void
2012 s390_emit_set_r2 (int arg1)
2014 unsigned char buf_s[] = {
2015 /* lhi %r2, <arg1> */
2016 0xa7, 0x28, (unsigned char) (arg1 >> 8), (unsigned char) arg1,
2018 static const unsigned char buf_l[] = {
2019 0x58, 0x20, 0x10, 0x00, /* l %r2, 0(%r1) */
2021 if (arg1 < 0x8000 && arg1 >= -0x8000)
2022 add_insns (buf_s, sizeof buf_s);
2023 else
2025 s390_emit_litpool (4);
2026 add_insns ((unsigned char *) &arg1, sizeof arg1);
2027 add_insns (buf_l, sizeof buf_l);
2031 /* The "emit_int_call_1" emit_ops method for s390. */
2033 static void
2034 s390_emit_int_call_1 (CORE_ADDR fn, int arg1)
2036 /* FN's prototype is `LONGEST(*fn)(int)'. */
2037 s390_emit_set_r2 (arg1);
2038 s390_emit_call (fn);
2041 /* The "emit_void_call_2" emit_ops method for s390. */
2043 static void
2044 s390_emit_void_call_2 (CORE_ADDR fn, int arg1)
2046 /* FN's prototype is `void(*fn)(int,LONGEST)'. */
2047 static const unsigned char buf[] = {
2048 0x18, 0xc2, /* lr %r12, %r2 */
2049 0x18, 0xd3, /* lr %r13, %r3 */
2050 0x18, 0x43, /* lr %r4, %r3 */
2051 0x18, 0x32, /* lr %r3, %r2 */
2053 static const unsigned char buf2[] = {
2054 0x18, 0x2c, /* lr %r2, %r12 */
2055 0x18, 0x3d, /* lr %r3, %r13 */
2057 add_insns (buf, sizeof buf);
2058 s390_emit_set_r2 (arg1);
2059 s390_emit_call (fn);
2060 add_insns (buf2, sizeof buf2);
2063 /* The "emit_eq_goto" emit_ops method for s390. */
2065 static void
2066 s390_emit_eq_goto (int *offset_p, int *size_p)
2068 static const unsigned char buf[] = {
2069 0x57, 0x20, 0xf0, 0x00, /* x %r2, 0(%r15) */
2070 0x57, 0x30, 0xf0, 0x04, /* x %r3, 4(%r15) */
2071 0x16, 0x23, /* or %r2, %r3 */
2072 0x98, 0x23, 0xf0, 0x08, /* lm %r2, %r3, 8(%r15) */
2073 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2074 0xc0, 0x84, 0x00, 0x00, 0x00, 0x00, /* jge <fillme> */
2076 add_insns (buf, sizeof buf);
2077 if (offset_p)
2078 *offset_p = 20;
2079 if (size_p)
2080 *size_p = 4;
2083 /* The "emit_ne_goto" emit_ops method for s390. */
2085 static void
2086 s390_emit_ne_goto (int *offset_p, int *size_p)
2088 static const unsigned char buf[] = {
2089 0x57, 0x20, 0xf0, 0x00, /* x %r2, 0(%r15) */
2090 0x57, 0x30, 0xf0, 0x04, /* x %r3, 4(%r15) */
2091 0x16, 0x23, /* or %r2, %r3 */
2092 0x98, 0x23, 0xf0, 0x08, /* lm %r2, %r3, 8(%r15) */
2093 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2094 0xc0, 0x74, 0x00, 0x00, 0x00, 0x00, /* jgne <fillme> */
2096 add_insns (buf, sizeof buf);
2097 if (offset_p)
2098 *offset_p = 20;
2099 if (size_p)
2100 *size_p = 4;
2103 /* The "emit_lt_goto" emit_ops method for s390. */
2105 static void
2106 s390_emit_lt_goto (int *offset_p, int *size_p)
2108 static const unsigned char buf[] = {
2109 0x59, 0x20, 0xf0, 0x00, /* c %r2, 0(%r15) */
2110 0xa7, 0x24, 0x00, 0x0e, /* jh .Ltrue */
2111 0xa7, 0x44, 0x00, 0x06, /* jl .Lfalse */
2112 0x55, 0x30, 0xf0, 0x04, /* cl %r3, 4(%r15) */
2113 0xa7, 0x24, 0x00, 0x08, /* jh .Ltrue */
2114 /* .Lfalse: */
2115 0x98, 0x23, 0xf0, 0x08, /* lm %r2, %r3, 8(%r15) */
2116 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2117 0xa7, 0xf4, 0x00, 0x09, /* j .Lend */
2118 /* .Ltrue: */
2119 0x98, 0x23, 0xf0, 0x08, /* lm %r2, %r3, 8(%r15) */
2120 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2121 0xc0, 0xf4, 0x00, 0x00, 0x00, 0x00, /* jg <fillme> */
2122 /* .Lend: */
2124 add_insns (buf, sizeof buf);
2125 if (offset_p)
2126 *offset_p = 42;
2127 if (size_p)
2128 *size_p = 4;
2131 /* The "emit_le_goto" emit_ops method for s390. */
2133 static void
2134 s390_emit_le_goto (int *offset_p, int *size_p)
2136 static const unsigned char buf[] = {
2137 0x59, 0x20, 0xf0, 0x00, /* c %r2, 0(%r15) */
2138 0xa7, 0x24, 0x00, 0x0e, /* jh .Ltrue */
2139 0xa7, 0x44, 0x00, 0x06, /* jl .Lfalse */
2140 0x55, 0x30, 0xf0, 0x04, /* cl %r3, 4(%r15) */
2141 0xa7, 0xa4, 0x00, 0x08, /* jhe .Ltrue */
2142 /* .Lfalse: */
2143 0x98, 0x23, 0xf0, 0x08, /* lm %r2, %r3, 8(%r15) */
2144 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2145 0xa7, 0xf4, 0x00, 0x09, /* j .Lend */
2146 /* .Ltrue: */
2147 0x98, 0x23, 0xf0, 0x08, /* lm %r2, %r3, 8(%r15) */
2148 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2149 0xc0, 0xf4, 0x00, 0x00, 0x00, 0x00, /* jg <fillme> */
2150 /* .Lend: */
2152 add_insns (buf, sizeof buf);
2153 if (offset_p)
2154 *offset_p = 42;
2155 if (size_p)
2156 *size_p = 4;
2159 /* The "emit_gt_goto" emit_ops method for s390. */
2161 static void
2162 s390_emit_gt_goto (int *offset_p, int *size_p)
2164 static const unsigned char buf[] = {
2165 0x59, 0x20, 0xf0, 0x00, /* c %r2, 0(%r15) */
2166 0xa7, 0x44, 0x00, 0x0e, /* jl .Ltrue */
2167 0xa7, 0x24, 0x00, 0x06, /* jh .Lfalse */
2168 0x55, 0x30, 0xf0, 0x04, /* cl %r3, 4(%r15) */
2169 0xa7, 0x44, 0x00, 0x08, /* jl .Ltrue */
2170 /* .Lfalse: */
2171 0x98, 0x23, 0xf0, 0x08, /* lm %r2, %r3, 8(%r15) */
2172 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2173 0xa7, 0xf4, 0x00, 0x09, /* j .Lend */
2174 /* .Ltrue: */
2175 0x98, 0x23, 0xf0, 0x08, /* lm %r2, %r3, 8(%r15) */
2176 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2177 0xc0, 0xf4, 0x00, 0x00, 0x00, 0x00, /* jg <fillme> */
2178 /* .Lend: */
2180 add_insns (buf, sizeof buf);
2181 if (offset_p)
2182 *offset_p = 42;
2183 if (size_p)
2184 *size_p = 4;
2187 /* The "emit_ge_goto" emit_ops method for s390. */
2189 static void
2190 s390_emit_ge_goto (int *offset_p, int *size_p)
2192 static const unsigned char buf[] = {
2193 0x59, 0x20, 0xf0, 0x00, /* c %r2, 0(%r15) */
2194 0xa7, 0x44, 0x00, 0x0e, /* jl .Ltrue */
2195 0xa7, 0x24, 0x00, 0x06, /* jh .Lfalse */
2196 0x55, 0x30, 0xf0, 0x04, /* cl %r3, 4(%r15) */
2197 0xa7, 0xc4, 0x00, 0x08, /* jle .Ltrue */
2198 /* .Lfalse: */
2199 0x98, 0x23, 0xf0, 0x08, /* lm %r2, %r3, 8(%r15) */
2200 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2201 0xa7, 0xf4, 0x00, 0x09, /* j .Lend */
2202 /* .Ltrue: */
2203 0x98, 0x23, 0xf0, 0x08, /* lm %r2, %r3, 8(%r15) */
2204 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2205 0xc0, 0xf4, 0x00, 0x00, 0x00, 0x00, /* jg <fillme> */
2206 /* .Lend: */
2208 add_insns (buf, sizeof buf);
2209 if (offset_p)
2210 *offset_p = 42;
2211 if (size_p)
2212 *size_p = 4;
2215 /* The "emit_ops" structure for s390. Named _impl to avoid name
2216 collision with s390_emit_ops function. */
2218 static struct emit_ops s390_emit_ops_impl =
2220 s390_emit_prologue,
2221 s390_emit_epilogue,
2222 s390_emit_add,
2223 s390_emit_sub,
2224 s390_emit_mul,
2225 s390_emit_lsh,
2226 s390_emit_rsh_signed,
2227 s390_emit_rsh_unsigned,
2228 s390_emit_ext,
2229 s390_emit_log_not,
2230 s390_emit_bit_and,
2231 s390_emit_bit_or,
2232 s390_emit_bit_xor,
2233 s390_emit_bit_not,
2234 s390_emit_equal,
2235 s390_emit_less_signed,
2236 s390_emit_less_unsigned,
2237 s390_emit_ref,
2238 s390_emit_if_goto,
2239 s390_emit_goto,
2240 s390_write_goto_address,
2241 s390_emit_const,
2242 s390_emit_call,
2243 s390_emit_reg,
2244 s390_emit_pop,
2245 s390_emit_stack_flush,
2246 s390_emit_zero_ext,
2247 s390_emit_swap,
2248 s390_emit_stack_adjust,
2249 s390_emit_int_call_1,
2250 s390_emit_void_call_2,
2251 s390_emit_eq_goto,
2252 s390_emit_ne_goto,
2253 s390_emit_lt_goto,
2254 s390_emit_le_goto,
2255 s390_emit_gt_goto,
2256 s390_emit_ge_goto
2259 #ifdef __s390x__
2261 /* The "emit_prologue" emit_ops method for s390x. */
2263 static void
2264 s390x_emit_prologue (void)
2266 static const unsigned char buf[] = {
2267 0xeb, 0x9f, 0xf0, 0x48, 0x00, 0x24, /* stmg %r9, %r15, 0x48(%r15) */
2268 0xb9, 0x04, 0x00, 0x92, /* lgr %r9, %r2 */
2269 0xb9, 0x04, 0x00, 0xa3, /* lgr %r10, %r3 */
2270 0xb9, 0x04, 0x00, 0xbf, /* lgr %r11, %r15 */
2272 add_insns (buf, sizeof buf);
2275 /* The "emit_epilogue" emit_ops method for s390x. */
2277 static void
2278 s390x_emit_epilogue (void)
2280 static const unsigned char buf[] = {
2281 0xe3, 0x20, 0xa0, 0x00, 0x00, 0x24, /* stg %r2, 0(%r10) */
2282 0xa7, 0x29, 0x00, 0x00, /* lghi %r2, 0 */
2283 0xeb, 0x9f, 0xf0, 0x48, 0x00, 0x04, /* lmg %r9, %r15, 0x48(%r15) */
2284 0x07, 0xfe, /* br %r14 */
2286 add_insns (buf, sizeof buf);
2289 /* The "emit_add" emit_ops method for s390x. */
2291 static void
2292 s390x_emit_add (void)
2294 static const unsigned char buf[] = {
2295 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x0a, /* alg %r2, 0(%r15) */
2296 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
2298 add_insns (buf, sizeof buf);
2301 /* The "emit_sub" emit_ops method for s390x. */
2303 static void
2304 s390x_emit_sub (void)
2306 static const unsigned char buf[] = {
2307 0xe3, 0x30, 0xf0, 0x00, 0x00, 0x04, /* lg %r3, 0(%r15) */
2308 0xb9, 0x0b, 0x00, 0x32, /* slgr %r3, %r2 */
2309 0xb9, 0x04, 0x00, 0x23, /* lgr %r2, %r3 */
2310 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
2312 add_insns (buf, sizeof buf);
2315 /* The "emit_mul" emit_ops method for s390x. */
2317 static void
2318 s390x_emit_mul (void)
2320 emit_error = 1;
2323 /* The "emit_lsh" emit_ops method for s390x. */
2325 static void
2326 s390x_emit_lsh (void)
2328 static const unsigned char buf[] = {
2329 0xe3, 0x30, 0xf0, 0x00, 0x00, 0x04, /* lg %r3, 0(%r15) */
2330 0xeb, 0x23, 0x20, 0x00, 0x00, 0x0d, /* sllg %r2, %r3, 0(%r2) */
2331 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
2333 add_insns (buf, sizeof buf);
2336 /* The "emit_rsh_signed" emit_ops method for s390x. */
2338 static void
2339 s390x_emit_rsh_signed (void)
2341 static const unsigned char buf[] = {
2342 0xe3, 0x30, 0xf0, 0x00, 0x00, 0x04, /* lg %r3, 0(%r15) */
2343 0xeb, 0x23, 0x20, 0x00, 0x00, 0x0a, /* srag %r2, %r3, 0(%r2) */
2344 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
2346 add_insns (buf, sizeof buf);
2349 /* The "emit_rsh_unsigned" emit_ops method for s390x. */
2351 static void
2352 s390x_emit_rsh_unsigned (void)
2354 static const unsigned char buf[] = {
2355 0xe3, 0x30, 0xf0, 0x00, 0x00, 0x04, /* lg %r3, 0(%r15) */
2356 0xeb, 0x23, 0x20, 0x00, 0x00, 0x0c, /* srlg %r2, %r3, 0(%r2) */
2357 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
2359 add_insns (buf, sizeof buf);
2362 /* The "emit_ext" emit_ops method for s390x. */
2364 static void
2365 s390x_emit_ext (int arg)
2367 unsigned char buf[] = {
2368 /* sllg %r2, %r2, <64-arg> */
2369 0xeb, 0x22, 0x00, (unsigned char) (64 - arg), 0x00, 0x0d,
2370 /* srag %r2, %r2, <64-arg> */
2371 0xeb, 0x22, 0x00, (unsigned char) (64 - arg), 0x00, 0x0a,
2373 add_insns (buf, sizeof buf);
2376 /* The "emit_log_not" emit_ops method for s390x. */
2378 static void
2379 s390x_emit_log_not (void)
2381 static const unsigned char buf[] = {
2382 0xb9, 0x00, 0x00, 0x22, /* lpgr %r2, %r2 */
2383 0xa7, 0x2b, 0xff, 0xff, /* aghi %r2, -1 */
2384 0xeb, 0x22, 0x00, 0x3f, 0x00, 0x0c, /* srlg %r2, %r2, 63 */
2386 add_insns (buf, sizeof buf);
2389 /* The "emit_bit_and" emit_ops method for s390x. */
2391 static void
2392 s390x_emit_bit_and (void)
2394 static const unsigned char buf[] = {
2395 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x80, /* ng %r2, 0(%r15) */
2396 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
2398 add_insns (buf, sizeof buf);
2401 /* The "emit_bit_or" emit_ops method for s390x. */
2403 static void
2404 s390x_emit_bit_or (void)
2406 static const unsigned char buf[] = {
2407 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x81, /* og %r2, 0(%r15) */
2408 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
2410 add_insns (buf, sizeof buf);
2413 /* The "emit_bit_xor" emit_ops method for s390x. */
2415 static void
2416 s390x_emit_bit_xor (void)
2418 static const unsigned char buf[] = {
2419 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x82, /* xg %r2, 0(%r15) */
2420 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
2422 add_insns (buf, sizeof buf);
2425 /* The "emit_bit_not" emit_ops method for s390x. */
2427 static void
2428 s390x_emit_bit_not (void)
2430 static const unsigned char buf[] = {
2431 0xa7, 0x39, 0xff, 0xff, /* lghi %r3, -1 */
2432 0xb9, 0x82, 0x00, 0x23, /* xgr %r2, %r3 */
2434 add_insns (buf, sizeof buf);
2437 /* The "emit_equal" emit_ops method for s390x. */
2439 static void
2440 s390x_emit_equal (void)
2442 s390x_emit_bit_xor ();
2443 s390x_emit_log_not ();
2446 /* The "emit_less_signed" emit_ops method for s390x. */
2448 static void
2449 s390x_emit_less_signed (void)
2451 static const unsigned char buf[] = {
2452 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20, /* cg %r2, 0(%r15) */
2453 0xa7, 0x29, 0x00, 0x01, /* lghi %r2, 1 */
2454 0xa7, 0x24, 0x00, 0x04, /* jh .Lend */
2455 0xa7, 0x29, 0x00, 0x00, /* lghi %r2, 0 */
2456 /* .Lend: */
2457 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
2459 add_insns (buf, sizeof buf);
2462 /* The "emit_less_unsigned" emit_ops method for s390x. */
2464 static void
2465 s390x_emit_less_unsigned (void)
2467 static const unsigned char buf[] = {
2468 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x21, /* clg %r2, 0(%r15) */
2469 0xa7, 0x29, 0x00, 0x01, /* lghi %r2, 1 */
2470 0xa7, 0x24, 0x00, 0x04, /* jh .Lend */
2471 0xa7, 0x29, 0x00, 0x00, /* lghi %r2, 0 */
2472 /* .Lend: */
2473 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
2475 add_insns (buf, sizeof buf);
2478 /* The "emit_ref" emit_ops method for s390x. */
2480 static void
2481 s390x_emit_ref (int size)
2483 static const unsigned char buf1[] = {
2484 0xe3, 0x20, 0x20, 0x00, 0x00, 0x90, /* llgc %r2, 0(%r2) */
2486 static const unsigned char buf2[] = {
2487 0xe3, 0x20, 0x20, 0x00, 0x00, 0x91 /* llgh %r2, 0(%r2) */
2489 static const unsigned char buf4[] = {
2490 0xe3, 0x20, 0x20, 0x00, 0x00, 0x16, /* llgf %r2, 0(%r2) */
2492 static const unsigned char buf8[] = {
2493 0xe3, 0x20, 0x20, 0x00, 0x00, 0x04, /* lg %r2, 0(%r2) */
2495 switch (size)
2497 case 1:
2498 add_insns (buf1, sizeof buf1);
2499 break;
2500 case 2:
2501 add_insns (buf2, sizeof buf2);
2502 break;
2503 case 4:
2504 add_insns (buf4, sizeof buf4);
2505 break;
2506 case 8:
2507 add_insns (buf8, sizeof buf8);
2508 break;
2509 default:
2510 emit_error = 1;
2514 /* The "emit_if_goto" emit_ops method for s390x. */
2516 static void
2517 s390x_emit_if_goto (int *offset_p, int *size_p)
2519 static const unsigned char buf[] = {
2520 0xb9, 0x02, 0x00, 0x22, /* ltgr %r2, %r2 */
2521 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x04, /* lg %r2, 0(%r15) */
2522 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
2523 0xc0, 0x74, 0x00, 0x00, 0x00, 0x00, /* jgne <fillme> */
2525 add_insns (buf, sizeof buf);
2526 if (offset_p)
2527 *offset_p = 16;
2528 if (size_p)
2529 *size_p = 4;
2532 /* The "emit_const" emit_ops method for s390x. */
2534 static void
2535 s390x_emit_const (LONGEST num)
2537 unsigned long long n = num;
2538 unsigned char buf_s[] = {
2539 /* lghi %r2, <num> */
2540 0xa7, 0x29, (unsigned char) (num >> 8), (unsigned char) num,
2542 static const unsigned char buf_l[] = {
2543 0xe3, 0x20, 0x10, 0x00, 0x00, 0x04, /* lg %r2, 0(%r1) */
2545 if (num < 0x8000 && num >= -0x8000)
2546 add_insns (buf_s, sizeof buf_s);
2547 else
2549 s390_emit_litpool (8);
2550 add_insns ((unsigned char *) &n, sizeof n);
2551 add_insns (buf_l, sizeof buf_l);
2555 /* The "emit_call" emit_ops method for s390x. */
2557 static void
2558 s390x_emit_call (CORE_ADDR fn)
2560 unsigned long n = fn;
2561 static const unsigned char buf[] = {
2562 0xe3, 0x10, 0x10, 0x00, 0x00, 0x04, /* lg %r1, 0(%r1) */
2563 0xa7, 0xfb, 0xff, 0x60, /* aghi %r15, -0xa0 */
2564 0x0d, 0xe1, /* basr %r14, %r1 */
2565 0xa7, 0xfb, 0x00, 0xa0, /* aghi %r15, 0xa0 */
2567 s390_emit_litpool (8);
2568 add_insns ((unsigned char *) &n, sizeof n);
2569 add_insns (buf, sizeof buf);
2572 /* The "emit_reg" emit_ops method for s390x. */
2574 static void
2575 s390x_emit_reg (int reg)
2577 unsigned char buf[] = {
2578 /* lgr %r2, %r9 */
2579 0xb9, 0x04, 0x00, 0x29,
2580 /* lghi %r3, <reg> */
2581 0xa7, 0x39, (unsigned char) (reg >> 8), (unsigned char) reg,
2583 add_insns (buf, sizeof buf);
2584 s390x_emit_call (get_raw_reg_func_addr ());
2587 /* The "emit_pop" emit_ops method for s390x. */
2589 static void
2590 s390x_emit_pop (void)
2592 static const unsigned char buf[] = {
2593 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x04, /* lg %r2, 0(%r15) */
2594 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
2596 add_insns (buf, sizeof buf);
2599 /* The "emit_stack_flush" emit_ops method for s390x. */
2601 static void
2602 s390x_emit_stack_flush (void)
2604 static const unsigned char buf[] = {
2605 0xa7, 0xfb, 0xff, 0xf8, /* aghi %r15, -8 */
2606 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x24, /* stg %r2, 0(%r15) */
2608 add_insns (buf, sizeof buf);
2611 /* The "emit_zero_ext" emit_ops method for s390x. */
2613 static void
2614 s390x_emit_zero_ext (int arg)
2616 unsigned char buf[] = {
2617 /* sllg %r2, %r2, <64-arg> */
2618 0xeb, 0x22, 0x00, (unsigned char) (64 - arg), 0x00, 0x0d,
2619 /* srlg %r2, %r2, <64-arg> */
2620 0xeb, 0x22, 0x00, (unsigned char) (64 - arg), 0x00, 0x0c,
2622 add_insns (buf, sizeof buf);
2625 /* The "emit_swap" emit_ops method for s390x. */
2627 static void
2628 s390x_emit_swap (void)
2630 static const unsigned char buf[] = {
2631 0xe3, 0x30, 0xf0, 0x00, 0x00, 0x04, /* lg %r3, 0(%r15) */
2632 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x24, /* stg %r2, 0(%r15) */
2633 0xb9, 0x04, 0x00, 0x23, /* lgr %r2, %r3 */
2635 add_insns (buf, sizeof buf);
2638 /* The "emit_stack_adjust" emit_ops method for s390x. */
2640 static void
2641 s390x_emit_stack_adjust (int n)
2643 unsigned char buf[] = {
2644 /* aghi %r15, 8*n */
2645 0xa7, 0xfb,
2646 (unsigned char) (n * 8 >> 8), (unsigned char) (n * 8),
2648 add_insns (buf, sizeof buf);
2651 /* The "emit_int_call_1" emit_ops method for s390x. */
2653 static void
2654 s390x_emit_int_call_1 (CORE_ADDR fn, int arg1)
2656 /* FN's prototype is `LONGEST(*fn)(int)'. */
2657 s390x_emit_const (arg1);
2658 s390x_emit_call (fn);
2661 /* The "emit_void_call_2" emit_ops method for s390x. */
2663 static void
2664 s390x_emit_void_call_2 (CORE_ADDR fn, int arg1)
2666 /* FN's prototype is `void(*fn)(int,LONGEST)'. */
2667 static const unsigned char buf[] = {
2668 0xb9, 0x04, 0x00, 0x32, /* lgr %r3, %r2 */
2669 0xb9, 0x04, 0x00, 0xc2, /* lgr %r12, %r2 */
2671 static const unsigned char buf2[] = {
2672 0xb9, 0x04, 0x00, 0x2c, /* lgr %r2, %r12 */
2674 add_insns (buf, sizeof buf);
2675 s390x_emit_const (arg1);
2676 s390x_emit_call (fn);
2677 add_insns (buf2, sizeof buf2);
2680 /* The "emit_eq_goto" emit_ops method for s390x. */
2682 static void
2683 s390x_emit_eq_goto (int *offset_p, int *size_p)
2685 static const unsigned char buf[] = {
2686 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20, /* cg %r2, 0(%r15) */
2687 0xe3, 0x20, 0xf0, 0x08, 0x00, 0x04, /* lg %r2, 8(%r15) */
2688 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2689 0xc0, 0x84, 0x00, 0x00, 0x00, 0x00, /* jge <fillme> */
2691 add_insns (buf, sizeof buf);
2692 if (offset_p)
2693 *offset_p = 18;
2694 if (size_p)
2695 *size_p = 4;
2698 /* The "emit_ne_goto" emit_ops method for s390x. */
2700 static void
2701 s390x_emit_ne_goto (int *offset_p, int *size_p)
2703 static const unsigned char buf[] = {
2704 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20, /* cg %r2, 0(%r15) */
2705 0xe3, 0x20, 0xf0, 0x08, 0x00, 0x04, /* lg %r2, 8(%r15) */
2706 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2707 0xc0, 0x74, 0x00, 0x00, 0x00, 0x00, /* jgne <fillme> */
2709 add_insns (buf, sizeof buf);
2710 if (offset_p)
2711 *offset_p = 18;
2712 if (size_p)
2713 *size_p = 4;
2716 /* The "emit_lt_goto" emit_ops method for s390x. */
2718 static void
2719 s390x_emit_lt_goto (int *offset_p, int *size_p)
2721 static const unsigned char buf[] = {
2722 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20, /* cg %r2, 0(%r15) */
2723 0xe3, 0x20, 0xf0, 0x08, 0x00, 0x04, /* lg %r2, 8(%r15) */
2724 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2725 0xc0, 0x24, 0x00, 0x00, 0x00, 0x00, /* jgh <fillme> */
2727 add_insns (buf, sizeof buf);
2728 if (offset_p)
2729 *offset_p = 18;
2730 if (size_p)
2731 *size_p = 4;
2734 /* The "emit_le_goto" emit_ops method for s390x. */
2736 static void
2737 s390x_emit_le_goto (int *offset_p, int *size_p)
2739 static const unsigned char buf[] = {
2740 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20, /* cg %r2, 0(%r15) */
2741 0xe3, 0x20, 0xf0, 0x08, 0x00, 0x04, /* lg %r2, 8(%r15) */
2742 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2743 0xc0, 0xa4, 0x00, 0x00, 0x00, 0x00, /* jghe <fillme> */
2745 add_insns (buf, sizeof buf);
2746 if (offset_p)
2747 *offset_p = 18;
2748 if (size_p)
2749 *size_p = 4;
2752 /* The "emit_gt_goto" emit_ops method for s390x. */
2754 static void
2755 s390x_emit_gt_goto (int *offset_p, int *size_p)
2757 static const unsigned char buf[] = {
2758 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20, /* cg %r2, 0(%r15) */
2759 0xe3, 0x20, 0xf0, 0x08, 0x00, 0x04, /* lg %r2, 8(%r15) */
2760 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2761 0xc0, 0x44, 0x00, 0x00, 0x00, 0x00, /* jgl <fillme> */
2763 add_insns (buf, sizeof buf);
2764 if (offset_p)
2765 *offset_p = 18;
2766 if (size_p)
2767 *size_p = 4;
2770 /* The "emit_ge_goto" emit_ops method for s390x. */
2772 static void
2773 s390x_emit_ge_goto (int *offset_p, int *size_p)
2775 static const unsigned char buf[] = {
2776 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20, /* cg %r2, 0(%r15) */
2777 0xe3, 0x20, 0xf0, 0x08, 0x00, 0x04, /* lg %r2, 8(%r15) */
2778 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2779 0xc0, 0xc4, 0x00, 0x00, 0x00, 0x00, /* jgle <fillme> */
2781 add_insns (buf, sizeof buf);
2782 if (offset_p)
2783 *offset_p = 18;
2784 if (size_p)
2785 *size_p = 4;
2788 /* The "emit_ops" structure for s390x. */
2790 static struct emit_ops s390x_emit_ops =
2792 s390x_emit_prologue,
2793 s390x_emit_epilogue,
2794 s390x_emit_add,
2795 s390x_emit_sub,
2796 s390x_emit_mul,
2797 s390x_emit_lsh,
2798 s390x_emit_rsh_signed,
2799 s390x_emit_rsh_unsigned,
2800 s390x_emit_ext,
2801 s390x_emit_log_not,
2802 s390x_emit_bit_and,
2803 s390x_emit_bit_or,
2804 s390x_emit_bit_xor,
2805 s390x_emit_bit_not,
2806 s390x_emit_equal,
2807 s390x_emit_less_signed,
2808 s390x_emit_less_unsigned,
2809 s390x_emit_ref,
2810 s390x_emit_if_goto,
2811 s390_emit_goto,
2812 s390_write_goto_address,
2813 s390x_emit_const,
2814 s390x_emit_call,
2815 s390x_emit_reg,
2816 s390x_emit_pop,
2817 s390x_emit_stack_flush,
2818 s390x_emit_zero_ext,
2819 s390x_emit_swap,
2820 s390x_emit_stack_adjust,
2821 s390x_emit_int_call_1,
2822 s390x_emit_void_call_2,
2823 s390x_emit_eq_goto,
2824 s390x_emit_ne_goto,
2825 s390x_emit_lt_goto,
2826 s390x_emit_le_goto,
2827 s390x_emit_gt_goto,
2828 s390x_emit_ge_goto
2830 #endif
2832 /* The "emit_ops" target ops method. */
2834 emit_ops *
2835 s390_target::emit_ops ()
2837 #ifdef __s390x__
2838 if (register_size (current_process ()->tdesc, 0) == 8)
2839 return &s390x_emit_ops;
2840 else
2841 #endif
2842 return &s390_emit_ops_impl;
2845 /* The linux target ops object. */
2847 linux_process_target *the_linux_target = &the_s390_target;
2849 void
2850 initialize_low_arch (void)
2852 /* Initialize the Linux target descriptions. */
2854 init_registers_s390_linux32 ();
2855 init_registers_s390_linux32v1 ();
2856 init_registers_s390_linux32v2 ();
2857 init_registers_s390_linux64 ();
2858 init_registers_s390_linux64v1 ();
2859 init_registers_s390_linux64v2 ();
2860 init_registers_s390_te_linux64 ();
2861 init_registers_s390_vx_linux64 ();
2862 init_registers_s390_tevx_linux64 ();
2863 init_registers_s390_gs_linux64 ();
2864 #ifdef __s390x__
2865 init_registers_s390x_linux64 ();
2866 init_registers_s390x_linux64v1 ();
2867 init_registers_s390x_linux64v2 ();
2868 init_registers_s390x_te_linux64 ();
2869 init_registers_s390x_vx_linux64 ();
2870 init_registers_s390x_tevx_linux64 ();
2871 init_registers_s390x_gs_linux64 ();
2872 #endif
2874 initialize_regsets_info (&s390_regsets_info);
2875 initialize_regsets_info (&s390_regsets_info_3264);