[PATCH 47/57][Arm][OBJDUMP] Add support for MVE instructions: vaddv, vmlaldav, vmlada...
[binutils-gdb.git] / gdb / gdbserver / linux-s390-low.c
blobf65a1ec38efd0faef3b0a5c7a52a725d54161e5c
1 /* GNU/Linux S/390 specific low level interface, for the remote server
2 for GDB.
3 Copyright (C) 2001-2019 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 "server.h"
23 #include "linux-low.h"
24 #include "elf/common.h"
25 #include "ax.h"
26 #include "tracepoint.h"
28 #include <asm/ptrace.h>
29 #include "nat/gdb_ptrace.h"
30 #include <sys/uio.h>
31 #include <elf.h>
32 #include <inttypes.h>
34 #include "linux-s390-tdesc.h"
36 #ifndef HWCAP_S390_HIGH_GPRS
37 #define HWCAP_S390_HIGH_GPRS 512
38 #endif
40 #ifndef HWCAP_S390_TE
41 #define HWCAP_S390_TE 1024
42 #endif
44 #ifndef HWCAP_S390_VX
45 #define HWCAP_S390_VX 2048
46 #endif
48 #ifndef HWCAP_S390_GS
49 #define HWCAP_S390_GS 16384
50 #endif
52 #define s390_num_regs 52
54 static int s390_regmap[] = {
55 PT_PSWMASK, PT_PSWADDR,
57 PT_GPR0, PT_GPR1, PT_GPR2, PT_GPR3,
58 PT_GPR4, PT_GPR5, PT_GPR6, PT_GPR7,
59 PT_GPR8, PT_GPR9, PT_GPR10, PT_GPR11,
60 PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15,
62 PT_ACR0, PT_ACR1, PT_ACR2, PT_ACR3,
63 PT_ACR4, PT_ACR5, PT_ACR6, PT_ACR7,
64 PT_ACR8, PT_ACR9, PT_ACR10, PT_ACR11,
65 PT_ACR12, PT_ACR13, PT_ACR14, PT_ACR15,
67 PT_FPC,
69 #ifndef __s390x__
70 PT_FPR0_HI, PT_FPR1_HI, PT_FPR2_HI, PT_FPR3_HI,
71 PT_FPR4_HI, PT_FPR5_HI, PT_FPR6_HI, PT_FPR7_HI,
72 PT_FPR8_HI, PT_FPR9_HI, PT_FPR10_HI, PT_FPR11_HI,
73 PT_FPR12_HI, PT_FPR13_HI, PT_FPR14_HI, PT_FPR15_HI,
74 #else
75 PT_FPR0, PT_FPR1, PT_FPR2, PT_FPR3,
76 PT_FPR4, PT_FPR5, PT_FPR6, PT_FPR7,
77 PT_FPR8, PT_FPR9, PT_FPR10, PT_FPR11,
78 PT_FPR12, PT_FPR13, PT_FPR14, PT_FPR15,
79 #endif
81 PT_ORIGGPR2,
84 #define s390_num_regs_3264 68
86 #ifdef __s390x__
87 static int s390_regmap_3264[] = {
88 PT_PSWMASK, PT_PSWADDR,
90 PT_GPR0, PT_GPR0, PT_GPR1, PT_GPR1,
91 PT_GPR2, PT_GPR2, PT_GPR3, PT_GPR3,
92 PT_GPR4, PT_GPR4, PT_GPR5, PT_GPR5,
93 PT_GPR6, PT_GPR6, PT_GPR7, PT_GPR7,
94 PT_GPR8, PT_GPR8, PT_GPR9, PT_GPR9,
95 PT_GPR10, PT_GPR10, PT_GPR11, PT_GPR11,
96 PT_GPR12, PT_GPR12, PT_GPR13, PT_GPR13,
97 PT_GPR14, PT_GPR14, PT_GPR15, PT_GPR15,
99 PT_ACR0, PT_ACR1, PT_ACR2, PT_ACR3,
100 PT_ACR4, PT_ACR5, PT_ACR6, PT_ACR7,
101 PT_ACR8, PT_ACR9, PT_ACR10, PT_ACR11,
102 PT_ACR12, PT_ACR13, PT_ACR14, PT_ACR15,
104 PT_FPC,
106 PT_FPR0, PT_FPR1, PT_FPR2, PT_FPR3,
107 PT_FPR4, PT_FPR5, PT_FPR6, PT_FPR7,
108 PT_FPR8, PT_FPR9, PT_FPR10, PT_FPR11,
109 PT_FPR12, PT_FPR13, PT_FPR14, PT_FPR15,
111 PT_ORIGGPR2,
113 #else
114 static int s390_regmap_3264[] = {
115 PT_PSWMASK, PT_PSWADDR,
117 -1, PT_GPR0, -1, PT_GPR1,
118 -1, PT_GPR2, -1, PT_GPR3,
119 -1, PT_GPR4, -1, PT_GPR5,
120 -1, PT_GPR6, -1, PT_GPR7,
121 -1, PT_GPR8, -1, PT_GPR9,
122 -1, PT_GPR10, -1, PT_GPR11,
123 -1, PT_GPR12, -1, PT_GPR13,
124 -1, PT_GPR14, -1, PT_GPR15,
126 PT_ACR0, PT_ACR1, PT_ACR2, PT_ACR3,
127 PT_ACR4, PT_ACR5, PT_ACR6, PT_ACR7,
128 PT_ACR8, PT_ACR9, PT_ACR10, PT_ACR11,
129 PT_ACR12, PT_ACR13, PT_ACR14, PT_ACR15,
131 PT_FPC,
133 PT_FPR0_HI, PT_FPR1_HI, PT_FPR2_HI, PT_FPR3_HI,
134 PT_FPR4_HI, PT_FPR5_HI, PT_FPR6_HI, PT_FPR7_HI,
135 PT_FPR8_HI, PT_FPR9_HI, PT_FPR10_HI, PT_FPR11_HI,
136 PT_FPR12_HI, PT_FPR13_HI, PT_FPR14_HI, PT_FPR15_HI,
138 PT_ORIGGPR2,
140 #endif
143 static int
144 s390_cannot_fetch_register (int regno)
146 return 0;
149 static int
150 s390_cannot_store_register (int regno)
152 return 0;
155 static void
156 s390_collect_ptrace_register (struct regcache *regcache, int regno, char *buf)
158 int size = register_size (regcache->tdesc, regno);
159 const struct regs_info *regs_info = (*the_low_target.regs_info) ();
160 struct usrregs_info *usr = regs_info->usrregs;
161 int regaddr = usr->regmap[regno];
163 if (size < sizeof (long))
165 memset (buf, 0, sizeof (long));
167 if ((regno ^ 1) < usr->num_regs
168 && usr->regmap[regno ^ 1] == regaddr)
170 collect_register (regcache, regno & ~1, buf);
171 collect_register (regcache, (regno & ~1) + 1,
172 buf + sizeof (long) - size);
174 else if (regaddr == PT_PSWMASK)
176 /* Convert 4-byte PSW mask to 8 bytes by clearing bit 12 and copying
177 the basic addressing mode bit from the PSW address. */
178 gdb_byte *addr = (gdb_byte *) alloca (register_size (regcache->tdesc, regno ^ 1));
179 collect_register (regcache, regno, buf);
180 collect_register (regcache, regno ^ 1, addr);
181 buf[1] &= ~0x8;
182 buf[size] |= (addr[0] & 0x80);
184 else if (regaddr == PT_PSWADDR)
186 /* Convert 4-byte PSW address to 8 bytes by clearing the addressing
187 mode bit (which gets copied to the PSW mask instead). */
188 collect_register (regcache, regno, buf + sizeof (long) - size);
189 buf[sizeof (long) - size] &= ~0x80;
191 else if ((regaddr >= PT_GPR0 && regaddr <= PT_GPR15)
192 || regaddr == PT_ORIGGPR2)
193 collect_register (regcache, regno, buf + sizeof (long) - size);
194 else
195 collect_register (regcache, regno, buf);
197 else if (regaddr != -1)
198 collect_register (regcache, regno, buf);
201 static void
202 s390_supply_ptrace_register (struct regcache *regcache,
203 int regno, const char *buf)
205 int size = register_size (regcache->tdesc, regno);
206 const struct regs_info *regs_info = (*the_low_target.regs_info) ();
207 struct usrregs_info *usr = regs_info->usrregs;
208 int regaddr = usr->regmap[regno];
210 if (size < sizeof (long))
212 if ((regno ^ 1) < usr->num_regs
213 && usr->regmap[regno ^ 1] == regaddr)
215 supply_register (regcache, regno & ~1, buf);
216 supply_register (regcache, (regno & ~1) + 1,
217 buf + sizeof (long) - size);
219 else if (regaddr == PT_PSWMASK)
221 /* Convert 8-byte PSW mask to 4 bytes by setting bit 12 and copying
222 the basic addressing mode into the PSW address. */
223 gdb_byte *mask = (gdb_byte *) alloca (size);
224 gdb_byte *addr = (gdb_byte *) alloca (register_size (regcache->tdesc, regno ^ 1));
225 memcpy (mask, buf, size);
226 mask[1] |= 0x8;
227 supply_register (regcache, regno, mask);
229 collect_register (regcache, regno ^ 1, addr);
230 addr[0] &= ~0x80;
231 addr[0] |= (buf[size] & 0x80);
232 supply_register (regcache, regno ^ 1, addr);
234 else if (regaddr == PT_PSWADDR)
236 /* Convert 8-byte PSW address to 4 bytes by truncating, but
237 keeping the addressing mode bit (which was set from the mask). */
238 gdb_byte *addr = (gdb_byte *) alloca (size);
239 char amode;
240 collect_register (regcache, regno, addr);
241 amode = addr[0] & 0x80;
242 memcpy (addr, buf + sizeof (long) - size, size);
243 addr[0] &= ~0x80;
244 addr[0] |= amode;
245 supply_register (regcache, regno, addr);
247 else if ((regaddr >= PT_GPR0 && regaddr <= PT_GPR15)
248 || regaddr == PT_ORIGGPR2)
249 supply_register (regcache, regno, buf + sizeof (long) - size);
250 else
251 supply_register (regcache, regno, buf);
253 else if (regaddr != -1)
254 supply_register (regcache, regno, buf);
257 /* Provide only a fill function for the general register set. ps_lgetregs
258 will use this for NPTL support. */
260 static void
261 s390_fill_gregset (struct regcache *regcache, void *buf)
263 int i;
264 const struct regs_info *regs_info = (*the_low_target.regs_info) ();
265 struct usrregs_info *usr = regs_info->usrregs;
267 for (i = 0; i < usr->num_regs; i++)
269 if (usr->regmap[i] < PT_PSWMASK
270 || usr->regmap[i] > PT_ACR15)
271 continue;
273 s390_collect_ptrace_register (regcache, i,
274 (char *) buf + usr->regmap[i]);
278 /* Fill and store functions for extended register sets. */
280 #ifndef __s390x__
281 static void
282 s390_fill_gprs_high (struct regcache *regcache, void *buf)
284 int r0h = find_regno (regcache->tdesc, "r0h");
285 int i;
287 for (i = 0; i < 16; i++)
288 collect_register (regcache, r0h + 2 * i, (char *) buf + 4 * i);
291 static void
292 s390_store_gprs_high (struct regcache *regcache, const void *buf)
294 int r0h = find_regno (regcache->tdesc, "r0h");
295 int i;
297 for (i = 0; i < 16; i++)
298 supply_register (regcache, r0h + 2 * i, (const char *) buf + 4 * i);
300 #endif
302 static void
303 s390_store_last_break (struct regcache *regcache, const void *buf)
305 const char *p;
307 p = (const char *) buf + 8 - register_size (regcache->tdesc, 0);
308 supply_register_by_name (regcache, "last_break", p);
311 static void
312 s390_fill_system_call (struct regcache *regcache, void *buf)
314 collect_register_by_name (regcache, "system_call", buf);
317 static void
318 s390_store_system_call (struct regcache *regcache, const void *buf)
320 supply_register_by_name (regcache, "system_call", buf);
323 static void
324 s390_store_tdb (struct regcache *regcache, const void *buf)
326 int tdb0 = find_regno (regcache->tdesc, "tdb0");
327 int tr0 = find_regno (regcache->tdesc, "tr0");
328 int i;
330 for (i = 0; i < 4; i++)
331 supply_register (regcache, tdb0 + i, (const char *) buf + 8 * i);
333 for (i = 0; i < 16; i++)
334 supply_register (regcache, tr0 + i, (const char *) buf + 8 * (16 + i));
337 static void
338 s390_fill_vxrs_low (struct regcache *regcache, void *buf)
340 int v0 = find_regno (regcache->tdesc, "v0l");
341 int i;
343 for (i = 0; i < 16; i++)
344 collect_register (regcache, v0 + i, (char *) buf + 8 * i);
347 static void
348 s390_store_vxrs_low (struct regcache *regcache, const void *buf)
350 int v0 = find_regno (regcache->tdesc, "v0l");
351 int i;
353 for (i = 0; i < 16; i++)
354 supply_register (regcache, v0 + i, (const char *) buf + 8 * i);
357 static void
358 s390_fill_vxrs_high (struct regcache *regcache, void *buf)
360 int v16 = find_regno (regcache->tdesc, "v16");
361 int i;
363 for (i = 0; i < 16; i++)
364 collect_register (regcache, v16 + i, (char *) buf + 16 * i);
367 static void
368 s390_store_vxrs_high (struct regcache *regcache, const void *buf)
370 int v16 = find_regno (regcache->tdesc, "v16");
371 int i;
373 for (i = 0; i < 16; i++)
374 supply_register (regcache, v16 + i, (const char *) buf + 16 * i);
377 static void
378 s390_store_gs (struct regcache *regcache, const void *buf)
380 int gsd = find_regno (regcache->tdesc, "gsd");
381 int i;
383 for (i = 0; i < 3; i++)
384 supply_register (regcache, gsd + i, (const char *) buf + 8 * (i + 1));
387 static void
388 s390_store_gsbc (struct regcache *regcache, const void *buf)
390 int bc_gsd = find_regno (regcache->tdesc, "bc_gsd");
391 int i;
393 for (i = 0; i < 3; i++)
394 supply_register (regcache, bc_gsd + i, (const char *) buf + 8 * (i + 1));
397 static struct regset_info s390_regsets[] = {
398 { 0, 0, 0, 0, GENERAL_REGS, s390_fill_gregset, NULL },
399 #ifndef __s390x__
400 { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_S390_HIGH_GPRS, 0,
401 EXTENDED_REGS, s390_fill_gprs_high, s390_store_gprs_high },
402 #endif
403 /* Last break address is read-only; no fill function. */
404 { PTRACE_GETREGSET, -1, NT_S390_LAST_BREAK, 0, EXTENDED_REGS,
405 NULL, s390_store_last_break },
406 { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_S390_SYSTEM_CALL, 0,
407 EXTENDED_REGS, s390_fill_system_call, s390_store_system_call },
408 /* TDB is read-only. */
409 { PTRACE_GETREGSET, -1, NT_S390_TDB, 0, EXTENDED_REGS,
410 NULL, s390_store_tdb },
411 { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_S390_VXRS_LOW, 0,
412 EXTENDED_REGS, s390_fill_vxrs_low, s390_store_vxrs_low },
413 { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_S390_VXRS_HIGH, 0,
414 EXTENDED_REGS, s390_fill_vxrs_high, s390_store_vxrs_high },
415 /* Guarded storage registers are read-only. */
416 { PTRACE_GETREGSET, -1, NT_S390_GS_CB, 0, EXTENDED_REGS,
417 NULL, s390_store_gs },
418 { PTRACE_GETREGSET, -1, NT_S390_GS_BC, 0, EXTENDED_REGS,
419 NULL, s390_store_gsbc },
420 NULL_REGSET
424 static const gdb_byte s390_breakpoint[] = { 0, 1 };
425 #define s390_breakpoint_len 2
427 /* Implementation of linux_target_ops method "sw_breakpoint_from_kind". */
429 static const gdb_byte *
430 s390_sw_breakpoint_from_kind (int kind, int *size)
432 *size = s390_breakpoint_len;
433 return s390_breakpoint;
436 static CORE_ADDR
437 s390_get_pc (struct regcache *regcache)
439 if (register_size (regcache->tdesc, 0) == 4)
441 unsigned int pswa;
442 collect_register_by_name (regcache, "pswa", &pswa);
443 return pswa & 0x7fffffff;
445 else
447 unsigned long pc;
448 collect_register_by_name (regcache, "pswa", &pc);
449 return pc;
453 static void
454 s390_set_pc (struct regcache *regcache, CORE_ADDR newpc)
456 if (register_size (regcache->tdesc, 0) == 4)
458 unsigned int pswa;
459 collect_register_by_name (regcache, "pswa", &pswa);
460 pswa = (pswa & 0x80000000) | (newpc & 0x7fffffff);
461 supply_register_by_name (regcache, "pswa", &pswa);
463 else
465 unsigned long pc = newpc;
466 supply_register_by_name (regcache, "pswa", &pc);
470 /* Determine the word size for the given PID, in bytes. */
472 #ifdef __s390x__
473 static int
474 s390_get_wordsize (int pid)
476 errno = 0;
477 PTRACE_XFER_TYPE pswm = ptrace (PTRACE_PEEKUSER, pid,
478 (PTRACE_TYPE_ARG3) 0,
479 (PTRACE_TYPE_ARG4) 0);
480 if (errno != 0)
482 warning (_("Couldn't determine word size, assuming 64-bit.\n"));
483 return 8;
485 /* Derive word size from extended addressing mode (PSW bit 31). */
486 return pswm & (1L << 32) ? 8 : 4;
488 #else
489 #define s390_get_wordsize(pid) 4
490 #endif
492 static int
493 s390_check_regset (int pid, int regset, int regsize)
495 void *buf = alloca (regsize);
496 struct iovec iov;
498 iov.iov_base = buf;
499 iov.iov_len = regsize;
501 if (ptrace (PTRACE_GETREGSET, pid, (long) regset, (long) &iov) >= 0
502 || errno == ENODATA)
503 return 1;
504 return 0;
507 /* For a 31-bit inferior, whether the kernel supports using the full
508 64-bit GPRs. */
509 static int have_hwcap_s390_high_gprs = 0;
510 static int have_hwcap_s390_vx = 0;
512 static void
513 s390_arch_setup (void)
515 const struct target_desc *tdesc;
516 struct regset_info *regset;
518 /* Determine word size and HWCAP. */
519 int pid = pid_of (current_thread);
520 int wordsize = s390_get_wordsize (pid);
521 unsigned long hwcap = linux_get_hwcap (wordsize);
523 /* Check whether the kernel supports extra register sets. */
524 int have_regset_last_break
525 = s390_check_regset (pid, NT_S390_LAST_BREAK, 8);
526 int have_regset_system_call
527 = s390_check_regset (pid, NT_S390_SYSTEM_CALL, 4);
528 int have_regset_tdb
529 = (s390_check_regset (pid, NT_S390_TDB, 256)
530 && (hwcap & HWCAP_S390_TE) != 0);
531 int have_regset_vxrs
532 = (s390_check_regset (pid, NT_S390_VXRS_LOW, 128)
533 && s390_check_regset (pid, NT_S390_VXRS_HIGH, 256)
534 && (hwcap & HWCAP_S390_VX) != 0);
535 int have_regset_gs
536 = (s390_check_regset (pid, NT_S390_GS_CB, 32)
537 && s390_check_regset (pid, NT_S390_GS_BC, 32)
538 && (hwcap & HWCAP_S390_GS) != 0);
541 #ifdef __s390x__
542 if (wordsize == 8)
544 if (have_regset_gs)
545 tdesc = tdesc_s390x_gs_linux64;
546 else if (have_regset_vxrs)
547 tdesc = (have_regset_tdb ? tdesc_s390x_tevx_linux64 :
548 tdesc_s390x_vx_linux64);
549 else if (have_regset_tdb)
550 tdesc = tdesc_s390x_te_linux64;
551 else if (have_regset_system_call)
552 tdesc = tdesc_s390x_linux64v2;
553 else if (have_regset_last_break)
554 tdesc = tdesc_s390x_linux64v1;
555 else
556 tdesc = tdesc_s390x_linux64;
559 /* For a 31-bit inferior, check whether the kernel supports
560 using the full 64-bit GPRs. */
561 else
562 #endif
563 if (hwcap & HWCAP_S390_HIGH_GPRS)
565 have_hwcap_s390_high_gprs = 1;
566 if (have_regset_gs)
567 tdesc = tdesc_s390_gs_linux64;
568 else if (have_regset_vxrs)
569 tdesc = (have_regset_tdb ? tdesc_s390_tevx_linux64 :
570 tdesc_s390_vx_linux64);
571 else if (have_regset_tdb)
572 tdesc = tdesc_s390_te_linux64;
573 else if (have_regset_system_call)
574 tdesc = tdesc_s390_linux64v2;
575 else if (have_regset_last_break)
576 tdesc = tdesc_s390_linux64v1;
577 else
578 tdesc = tdesc_s390_linux64;
580 else
582 /* Assume 31-bit inferior process. */
583 if (have_regset_system_call)
584 tdesc = tdesc_s390_linux32v2;
585 else if (have_regset_last_break)
586 tdesc = tdesc_s390_linux32v1;
587 else
588 tdesc = tdesc_s390_linux32;
591 have_hwcap_s390_vx = have_regset_vxrs;
594 /* Update target_regsets according to available register sets. */
595 for (regset = s390_regsets; regset->size >= 0; regset++)
596 if (regset->get_request == PTRACE_GETREGSET)
597 switch (regset->nt_type)
599 #ifndef __s390x__
600 case NT_S390_HIGH_GPRS:
601 regset->size = have_hwcap_s390_high_gprs ? 64 : 0;
602 break;
603 #endif
604 case NT_S390_LAST_BREAK:
605 regset->size = have_regset_last_break ? 8 : 0;
606 break;
607 case NT_S390_SYSTEM_CALL:
608 regset->size = have_regset_system_call ? 4 : 0;
609 break;
610 case NT_S390_TDB:
611 regset->size = have_regset_tdb ? 256 : 0;
612 break;
613 case NT_S390_VXRS_LOW:
614 regset->size = have_regset_vxrs ? 128 : 0;
615 break;
616 case NT_S390_VXRS_HIGH:
617 regset->size = have_regset_vxrs ? 256 : 0;
618 break;
619 case NT_S390_GS_CB:
620 case NT_S390_GS_BC:
621 regset->size = have_regset_gs ? 32 : 0;
622 default:
623 break;
626 current_process ()->tdesc = tdesc;
630 static int
631 s390_breakpoint_at (CORE_ADDR pc)
633 unsigned char c[s390_breakpoint_len];
634 read_inferior_memory (pc, c, s390_breakpoint_len);
635 return memcmp (c, s390_breakpoint, s390_breakpoint_len) == 0;
638 /* Breakpoint/Watchpoint support. */
640 /* The "supports_z_point_type" linux_target_ops method. */
642 static int
643 s390_supports_z_point_type (char z_type)
645 switch (z_type)
647 case Z_PACKET_SW_BP:
648 return 1;
649 default:
650 return 0;
654 /* Support for hardware single step. */
656 static int
657 s390_supports_hardware_single_step (void)
659 return 1;
662 static struct usrregs_info s390_usrregs_info =
664 s390_num_regs,
665 s390_regmap,
668 static struct regsets_info s390_regsets_info =
670 s390_regsets, /* regsets */
671 0, /* num_regsets */
672 NULL, /* disabled_regsets */
675 static struct regs_info regs_info =
677 NULL, /* regset_bitmap */
678 &s390_usrregs_info,
679 &s390_regsets_info
682 static struct usrregs_info s390_usrregs_info_3264 =
684 s390_num_regs_3264,
685 s390_regmap_3264
688 static struct regsets_info s390_regsets_info_3264 =
690 s390_regsets, /* regsets */
691 0, /* num_regsets */
692 NULL, /* disabled_regsets */
695 static struct regs_info regs_info_3264 =
697 NULL, /* regset_bitmap */
698 &s390_usrregs_info_3264,
699 &s390_regsets_info_3264
702 static const struct regs_info *
703 s390_regs_info (void)
705 if (have_hwcap_s390_high_gprs)
707 #ifdef __s390x__
708 const struct target_desc *tdesc = current_process ()->tdesc;
710 if (register_size (tdesc, 0) == 4)
711 return &regs_info_3264;
712 #else
713 return &regs_info_3264;
714 #endif
716 return &regs_info;
719 /* The "supports_tracepoints" linux_target_ops method. */
721 static int
722 s390_supports_tracepoints (void)
724 return 1;
727 /* Implementation of linux_target_ops method "get_thread_area". */
729 static int
730 s390_get_thread_area (int lwpid, CORE_ADDR *addrp)
732 CORE_ADDR res = ptrace (PTRACE_PEEKUSER, lwpid, (long) PT_ACR0, (long) 0);
733 #ifdef __s390x__
734 struct regcache *regcache = get_thread_regcache (current_thread, 0);
736 if (register_size (regcache->tdesc, 0) == 4)
737 res &= 0xffffffffull;
738 #endif
739 *addrp = res;
740 return 0;
744 /* Fast tracepoint support.
746 The register save area on stack is identical for all targets:
748 0x000+i*0x10: VR0-VR31
749 0x200+i*8: GR0-GR15
750 0x280+i*4: AR0-AR15
751 0x2c0: PSWM [64-bit]
752 0x2c8: PSWA [64-bit]
753 0x2d0: FPC
755 If we're on 31-bit linux, we just don't store the high parts of the GPRs.
756 Likewise, if there's no VX support, we just store the FRs into the slots
757 of low VR halves. The agent code is responsible for rearranging that
758 into regcache. */
760 /* Code sequence saving GPRs for 31-bit target with no high GPRs. There's
761 one trick used at the very beginning: since there's no way to allocate
762 stack space without destroying CC (lay instruction can do it, but it's
763 only supported on later CPUs), we take 4 different execution paths for
764 every possible value of CC, allocate stack space, save %r0, stuff the
765 CC value in %r0 (shifted to match its position in PSWM high word),
766 then branch to common path. */
768 static const unsigned char s390_ft_entry_gpr_esa[] = {
769 0xa7, 0x14, 0x00, 0x1e, /* jo .Lcc3 */
770 0xa7, 0x24, 0x00, 0x14, /* jh .Lcc2 */
771 0xa7, 0x44, 0x00, 0x0a, /* jl .Lcc1 */
772 /* CC = 0 */
773 0xa7, 0xfa, 0xfd, 0x00, /* ahi %r15, -0x300 */
774 0x50, 0x00, 0xf2, 0x04, /* st %r0, 0x204(%r15) */
775 0xa7, 0x08, 0x00, 0x00, /* lhi %r0, 0 */
776 0xa7, 0xf4, 0x00, 0x18, /* j .Lccdone */
777 /* .Lcc1: */
778 0xa7, 0xfa, 0xfd, 0x00, /* ahi %r15, -0x300 */
779 0x50, 0x00, 0xf2, 0x04, /* st %r0, 0x204(%r15) */
780 0xa7, 0x08, 0x10, 0x00, /* lhi %r0, 0x1000 */
781 0xa7, 0xf4, 0x00, 0x10, /* j .Lccdone */
782 /* .Lcc2: */
783 0xa7, 0xfa, 0xfd, 0x00, /* ahi %r15, -0x300 */
784 0x50, 0x00, 0xf2, 0x04, /* st %r0, 0x204(%r15) */
785 0xa7, 0x08, 0x20, 0x00, /* lhi %r0, 0x2000 */
786 0xa7, 0xf4, 0x00, 0x08, /* j .Lccdone */
787 /* .Lcc3: */
788 0xa7, 0xfa, 0xfd, 0x00, /* ahi %r15, -0x300 */
789 0x50, 0x00, 0xf2, 0x04, /* st %r0, 0x204(%r15) */
790 0xa7, 0x08, 0x30, 0x00, /* lhi %r0, 0x3000 */
791 /* .Lccdone: */
792 0x50, 0x10, 0xf2, 0x0c, /* st %r1, 0x20c(%r15) */
793 0x50, 0x20, 0xf2, 0x14, /* st %r2, 0x214(%r15) */
794 0x50, 0x30, 0xf2, 0x1c, /* st %r3, 0x21c(%r15) */
795 0x50, 0x40, 0xf2, 0x24, /* st %r4, 0x224(%r15) */
796 0x50, 0x50, 0xf2, 0x2c, /* st %r5, 0x22c(%r15) */
797 0x50, 0x60, 0xf2, 0x34, /* st %r6, 0x234(%r15) */
798 0x50, 0x70, 0xf2, 0x3c, /* st %r7, 0x23c(%r15) */
799 0x50, 0x80, 0xf2, 0x44, /* st %r8, 0x244(%r15) */
800 0x50, 0x90, 0xf2, 0x4c, /* st %r9, 0x24c(%r15) */
801 0x50, 0xa0, 0xf2, 0x54, /* st %r10, 0x254(%r15) */
802 0x50, 0xb0, 0xf2, 0x5c, /* st %r11, 0x25c(%r15) */
803 0x50, 0xc0, 0xf2, 0x64, /* st %r12, 0x264(%r15) */
804 0x50, 0xd0, 0xf2, 0x6c, /* st %r13, 0x26c(%r15) */
805 0x50, 0xe0, 0xf2, 0x74, /* st %r14, 0x274(%r15) */
806 /* Compute original value of %r15 and store it. We use ahi instead
807 of la to preserve the whole value, and not just the low 31 bits.
808 This is not particularly important here, but essential in the
809 zarch case where someone might be using the high word of %r15
810 as an extra register. */
811 0x18, 0x1f, /* lr %r1, %r15 */
812 0xa7, 0x1a, 0x03, 0x00, /* ahi %r1, 0x300 */
813 0x50, 0x10, 0xf2, 0x7c, /* st %r1, 0x27c(%r15) */
816 /* Code sequence saving GPRs for 31-bit target with high GPRs and for 64-bit
817 target. Same as above, except this time we can use load/store multiple,
818 since the 64-bit regs are tightly packed. */
820 static const unsigned char s390_ft_entry_gpr_zarch[] = {
821 0xa7, 0x14, 0x00, 0x21, /* jo .Lcc3 */
822 0xa7, 0x24, 0x00, 0x16, /* jh .Lcc2 */
823 0xa7, 0x44, 0x00, 0x0b, /* jl .Lcc1 */
824 /* CC = 0 */
825 0xa7, 0xfb, 0xfd, 0x00, /* aghi %r15, -0x300 */
826 0xeb, 0x0e, 0xf2, 0x00, 0x00, 0x24, /* stmg %r0, %r14, 0x200(%r15) */
827 0xa7, 0x08, 0x00, 0x00, /* lhi %r0, 0 */
828 0xa7, 0xf4, 0x00, 0x1b, /* j .Lccdone */
829 /* .Lcc1: */
830 0xa7, 0xfb, 0xfd, 0x00, /* aghi %r15, -0x300 */
831 0xeb, 0x0e, 0xf2, 0x00, 0x00, 0x24, /* stmg %r0, %r14, 0x200(%r15) */
832 0xa7, 0x08, 0x10, 0x00, /* lhi %r0, 0x1000 */
833 0xa7, 0xf4, 0x00, 0x12, /* j .Lccdone */
834 /* .Lcc2: */
835 0xa7, 0xfb, 0xfd, 0x00, /* aghi %r15, -0x300 */
836 0xeb, 0x0e, 0xf2, 0x00, 0x00, 0x24, /* stmg %r0, %r14, 0x200(%r15) */
837 0xa7, 0x08, 0x20, 0x00, /* lhi %r0, 0x2000 */
838 0xa7, 0xf4, 0x00, 0x09, /* j .Lccdone */
839 /* .Lcc3: */
840 0xa7, 0xfb, 0xfd, 0x00, /* aghi %r15, -0x300 */
841 0xeb, 0x0e, 0xf2, 0x00, 0x00, 0x24, /* stmg %r0, %r14, 0x200(%r15) */
842 0xa7, 0x08, 0x30, 0x00, /* lhi %r0, 0x3000 */
843 /* .Lccdone: */
844 0xb9, 0x04, 0x00, 0x1f, /* lgr %r1, %r15 */
845 0xa7, 0x1b, 0x03, 0x00, /* aghi %r1, 0x300 */
846 0xe3, 0x10, 0xf2, 0x78, 0x00, 0x24, /* stg %r1, 0x278(%r15) */
849 /* Code sequence saving ARs, PSWM and FPC. PSWM has to be assembled from
850 current PSWM (read by epsw) and CC from entry (in %r0). */
852 static const unsigned char s390_ft_entry_misc[] = {
853 0x9b, 0x0f, 0xf2, 0x80, /* stam %a0, %a15, 0x20(%%r15) */
854 0xb9, 0x8d, 0x00, 0x23, /* epsw %r2, %r3 */
855 0xa7, 0x18, 0xcf, 0xff, /* lhi %r1, ~0x3000 */
856 0x14, 0x21, /* nr %r2, %r1 */
857 0x16, 0x20, /* or %r2, %r0 */
858 0x50, 0x20, 0xf2, 0xc0, /* st %r2, 0x2c0(%r15) */
859 0x50, 0x30, 0xf2, 0xc4, /* st %r3, 0x2c4(%r15) */
860 0xb2, 0x9c, 0xf2, 0xd0, /* stfpc 0x2d0(%r15) */
863 /* Code sequence saving FRs, used if VX not supported. */
865 static const unsigned char s390_ft_entry_fr[] = {
866 0x60, 0x00, 0xf0, 0x00, /* std %f0, 0x000(%r15) */
867 0x60, 0x10, 0xf0, 0x10, /* std %f1, 0x010(%r15) */
868 0x60, 0x20, 0xf0, 0x20, /* std %f2, 0x020(%r15) */
869 0x60, 0x30, 0xf0, 0x30, /* std %f3, 0x030(%r15) */
870 0x60, 0x40, 0xf0, 0x40, /* std %f4, 0x040(%r15) */
871 0x60, 0x50, 0xf0, 0x50, /* std %f5, 0x050(%r15) */
872 0x60, 0x60, 0xf0, 0x60, /* std %f6, 0x060(%r15) */
873 0x60, 0x70, 0xf0, 0x70, /* std %f7, 0x070(%r15) */
874 0x60, 0x80, 0xf0, 0x80, /* std %f8, 0x080(%r15) */
875 0x60, 0x90, 0xf0, 0x90, /* std %f9, 0x090(%r15) */
876 0x60, 0xa0, 0xf0, 0xa0, /* std %f10, 0x0a0(%r15) */
877 0x60, 0xb0, 0xf0, 0xb0, /* std %f11, 0x0b0(%r15) */
878 0x60, 0xc0, 0xf0, 0xc0, /* std %f12, 0x0c0(%r15) */
879 0x60, 0xd0, 0xf0, 0xd0, /* std %f13, 0x0d0(%r15) */
880 0x60, 0xe0, 0xf0, 0xe0, /* std %f14, 0x0e0(%r15) */
881 0x60, 0xf0, 0xf0, 0xf0, /* std %f15, 0x0f0(%r15) */
884 /* Code sequence saving VRs, used if VX not supported. */
886 static const unsigned char s390_ft_entry_vr[] = {
887 0xe7, 0x0f, 0xf0, 0x00, 0x00, 0x3e, /* vstm %v0, %v15, 0x000(%r15) */
888 0xe7, 0x0f, 0xf1, 0x00, 0x0c, 0x3e, /* vstm %v16, %v31, 0x100(%r15) */
891 /* Code sequence doing the collection call for 31-bit target. %r1 contains
892 the address of the literal pool. */
894 static const unsigned char s390_ft_main_31[] = {
895 /* Load the literals into registers. */
896 0x58, 0x50, 0x10, 0x00, /* l %r5, 0x0(%r1) */
897 0x58, 0x20, 0x10, 0x04, /* l %r2, 0x4(%r1) */
898 0x58, 0x40, 0x10, 0x08, /* l %r4, 0x8(%r1) */
899 0x58, 0x60, 0x10, 0x0c, /* l %r6, 0xc(%r1) */
900 /* Save original PSWA (tracepoint address | 0x80000000). */
901 0x50, 0x50, 0xf2, 0xcc, /* st %r5, 0x2cc(%r15) */
902 /* Construct a collecting_t object at %r15+0x2e0. */
903 0x50, 0x20, 0xf2, 0xe0, /* st %r2, 0x2e0(%r15) */
904 0x9b, 0x00, 0xf2, 0xe4, /* stam %a0, %a0, 0x2e4(%r15) */
905 /* Move its address to %r0. */
906 0x41, 0x00, 0xf2, 0xe0, /* la %r0, 0x2e0(%r15) */
907 /* Take the lock. */
908 /* .Lloop: */
909 0xa7, 0x18, 0x00, 0x00, /* lhi %r1, 0 */
910 0xba, 0x10, 0x60, 0x00, /* cs %r1, %r0, 0(%r6) */
911 0xa7, 0x74, 0xff, 0xfc, /* jne .Lloop */
912 /* Address of the register save block to %r3. */
913 0x18, 0x3f, /* lr %r3, %r15 */
914 /* Make a stack frame, so that we can call the collector. */
915 0xa7, 0xfa, 0xff, 0xa0, /* ahi %r15, -0x60 */
916 /* Call it. */
917 0x0d, 0xe4, /* basr %r14, %r4 */
918 /* And get rid of the stack frame again. */
919 0x41, 0xf0, 0xf0, 0x60, /* la %r15, 0x60(%r15) */
920 /* Leave the lock. */
921 0x07, 0xf0, /* br %r0 */
922 0xa7, 0x18, 0x00, 0x00, /* lhi %r1, 0 */
923 0x50, 0x10, 0x60, 0x00, /* st %t1, 0(%r6) */
926 /* Code sequence doing the collection call for 64-bit target. %r1 contains
927 the address of the literal pool. */
929 static const unsigned char s390_ft_main_64[] = {
930 /* Load the literals into registers. */
931 0xe3, 0x50, 0x10, 0x00, 0x00, 0x04, /* lg %r5, 0x00(%r1) */
932 0xe3, 0x20, 0x10, 0x08, 0x00, 0x04, /* lg %r2, 0x08(%r1) */
933 0xe3, 0x40, 0x10, 0x10, 0x00, 0x04, /* lg %r4, 0x10(%r1) */
934 0xe3, 0x60, 0x10, 0x18, 0x00, 0x04, /* lg %r6, 0x18(%r1) */
935 /* Save original PSWA (tracepoint address). */
936 0xe3, 0x50, 0xf2, 0xc8, 0x00, 0x24, /* stg %r5, 0x2c8(%r15) */
937 /* Construct a collecting_t object at %r15+0x2e0. */
938 0xe3, 0x20, 0xf2, 0xe0, 0x00, 0x24, /* stg %r2, 0x2e0(%r15) */
939 0x9b, 0x01, 0xf2, 0xe8, /* stam %a0, %a1, 0x2e8(%r15) */
940 /* Move its address to %r0. */
941 0x41, 0x00, 0xf2, 0xe0, /* la %r0, 0x2e0(%r15) */
942 /* Take the lock. */
943 /* .Lloop: */
944 0xa7, 0x19, 0x00, 0x00, /* lghi %r1, 0 */
945 0xeb, 0x10, 0x60, 0x00, 0x00, 0x30, /* csg %r1, %r0, 0(%r6) */
946 0xa7, 0x74, 0xff, 0xfb, /* jne .Lloop */
947 /* Address of the register save block to %r3. */
948 0xb9, 0x04, 0x00, 0x3f, /* lgr %r3, %r15 */
949 /* Make a stack frame, so that we can call the collector. */
950 0xa7, 0xfb, 0xff, 0x60, /* aghi %r15, -0xa0 */
951 /* Call it. */
952 0x0d, 0xe4, /* basr %r14, %r4 */
953 /* And get rid of the stack frame again. */
954 0x41, 0xf0, 0xf0, 0xa0, /* la %r15, 0xa0(%r15) */
955 /* Leave the lock. */
956 0x07, 0xf0, /* br %r0 */
957 0xa7, 0x19, 0x00, 0x00, /* lghi %r1, 0 */
958 0xe3, 0x10, 0x60, 0x00, 0x00, 0x24, /* stg %t1, 0(%r6) */
961 /* Code sequence restoring FRs, for targets with no VX support. */
963 static const unsigned char s390_ft_exit_fr[] = {
964 0x68, 0x00, 0xf0, 0x00, /* ld %f0, 0x000(%r15) */
965 0x68, 0x10, 0xf0, 0x10, /* ld %f1, 0x010(%r15) */
966 0x68, 0x20, 0xf0, 0x20, /* ld %f2, 0x020(%r15) */
967 0x68, 0x30, 0xf0, 0x30, /* ld %f3, 0x030(%r15) */
968 0x68, 0x40, 0xf0, 0x40, /* ld %f4, 0x040(%r15) */
969 0x68, 0x50, 0xf0, 0x50, /* ld %f5, 0x050(%r15) */
970 0x68, 0x60, 0xf0, 0x60, /* ld %f6, 0x060(%r15) */
971 0x68, 0x70, 0xf0, 0x70, /* ld %f7, 0x070(%r15) */
972 0x68, 0x80, 0xf0, 0x80, /* ld %f8, 0x080(%r15) */
973 0x68, 0x90, 0xf0, 0x90, /* ld %f9, 0x090(%r15) */
974 0x68, 0xa0, 0xf0, 0xa0, /* ld %f10, 0x0a0(%r15) */
975 0x68, 0xb0, 0xf0, 0xb0, /* ld %f11, 0x0b0(%r15) */
976 0x68, 0xc0, 0xf0, 0xc0, /* ld %f12, 0x0c0(%r15) */
977 0x68, 0xd0, 0xf0, 0xd0, /* ld %f13, 0x0d0(%r15) */
978 0x68, 0xe0, 0xf0, 0xe0, /* ld %f14, 0x0e0(%r15) */
979 0x68, 0xf0, 0xf0, 0xf0, /* ld %f15, 0x0f0(%r15) */
982 /* Code sequence restoring VRs. */
984 static const unsigned char s390_ft_exit_vr[] = {
985 0xe7, 0x0f, 0xf0, 0x00, 0x00, 0x36, /* vlm %v0, %v15, 0x000(%r15) */
986 0xe7, 0x0f, 0xf1, 0x00, 0x0c, 0x36, /* vlm %v16, %v31, 0x100(%r15) */
989 /* Code sequence restoring misc registers. As for PSWM, only CC should be
990 modified by C code, so we use the alr instruction to restore it by
991 manufacturing an operand that'll result in the original flags. */
993 static const unsigned char s390_ft_exit_misc[] = {
994 0xb2, 0x9d, 0xf2, 0xd0, /* lfpc 0x2d0(%r15) */
995 0x58, 0x00, 0xf2, 0xc0, /* l %r0, 0x2c0(%r15) */
996 /* Extract CC to high 2 bits of %r0. */
997 0x88, 0x00, 0x00, 0x0c, /* srl %r0, 12 */
998 0x89, 0x00, 0x00, 0x1e, /* sll %r0, 30 */
999 /* Add %r0 to itself. Result will be nonzero iff CC bit 0 is set, and
1000 will have carry iff CC bit 1 is set - resulting in the same flags
1001 as the original. */
1002 0x1e, 0x00, /* alr %r0, %r0 */
1003 0x9a, 0x0f, 0xf2, 0x80, /* lam %a0, %a15, 0x280(%r15) */
1006 /* Code sequence restoring GPRs, for 31-bit targets with no high GPRs. */
1008 static const unsigned char s390_ft_exit_gpr_esa[] = {
1009 0x58, 0x00, 0xf2, 0x04, /* l %r0, 0x204(%r15) */
1010 0x58, 0x10, 0xf2, 0x0c, /* l %r1, 0x20c(%r15) */
1011 0x58, 0x20, 0xf2, 0x14, /* l %r2, 0x214(%r15) */
1012 0x58, 0x30, 0xf2, 0x1c, /* l %r3, 0x21c(%r15) */
1013 0x58, 0x40, 0xf2, 0x24, /* l %r4, 0x224(%r15) */
1014 0x58, 0x50, 0xf2, 0x2c, /* l %r5, 0x22c(%r15) */
1015 0x58, 0x60, 0xf2, 0x34, /* l %r6, 0x234(%r15) */
1016 0x58, 0x70, 0xf2, 0x3c, /* l %r7, 0x23c(%r15) */
1017 0x58, 0x80, 0xf2, 0x44, /* l %r8, 0x244(%r15) */
1018 0x58, 0x90, 0xf2, 0x4c, /* l %r9, 0x24c(%r15) */
1019 0x58, 0xa0, 0xf2, 0x54, /* l %r10, 0x254(%r15) */
1020 0x58, 0xb0, 0xf2, 0x5c, /* l %r11, 0x25c(%r15) */
1021 0x58, 0xc0, 0xf2, 0x64, /* l %r12, 0x264(%r15) */
1022 0x58, 0xd0, 0xf2, 0x6c, /* l %r13, 0x26c(%r15) */
1023 0x58, 0xe0, 0xf2, 0x74, /* l %r14, 0x274(%r15) */
1024 0x58, 0xf0, 0xf2, 0x7c, /* l %r15, 0x27c(%r15) */
1027 /* Code sequence restoring GPRs, for 64-bit targets and 31-bit targets
1028 with high GPRs. */
1030 static const unsigned char s390_ft_exit_gpr_zarch[] = {
1031 0xeb, 0x0f, 0xf2, 0x00, 0x00, 0x04, /* lmg %r0, %r15, 0x200(%r15) */
1034 /* Writes instructions to target, updating the to pointer. */
1036 static void
1037 append_insns (CORE_ADDR *to, size_t len, const unsigned char *buf)
1039 write_inferior_memory (*to, buf, len);
1040 *to += len;
1043 /* Relocates an instruction from oldloc to *to, updating to. */
1045 static int
1046 s390_relocate_instruction (CORE_ADDR *to, CORE_ADDR oldloc, int is_64)
1048 gdb_byte buf[6];
1049 int ilen;
1050 int op2;
1051 /* 0: no fixup, 1: PC16DBL fixup, 2: PC32DBL fixup. */
1052 int mode = 0;
1053 int is_bras = 0;
1054 read_inferior_memory (oldloc, buf, sizeof buf);
1055 if (buf[0] < 0x40)
1056 ilen = 2;
1057 else if (buf[0] < 0xc0)
1058 ilen = 4;
1059 else
1060 ilen = 6;
1061 switch (buf[0])
1063 case 0x05: /* BALR */
1064 case 0x0c: /* BASSM */
1065 case 0x0d: /* BASR */
1066 case 0x45: /* BAL */
1067 case 0x4d: /* BAS */
1068 /* These save a return address and mess around with registers.
1069 We can't relocate them. */
1070 return 1;
1071 case 0x84: /* BRXH */
1072 case 0x85: /* BRXLE */
1073 mode = 1;
1074 break;
1075 case 0xa7:
1076 op2 = buf[1] & 0xf;
1077 /* BRC, BRAS, BRCT, BRCTG */
1078 if (op2 >= 4 && op2 <= 7)
1079 mode = 1;
1080 /* BRAS */
1081 if (op2 == 5)
1082 is_bras = 1;
1083 break;
1084 case 0xc0:
1085 op2 = buf[1] & 0xf;
1086 /* LARL, BRCL, BRASL */
1087 if (op2 == 0 || op2 == 4 || op2 == 5)
1088 mode = 2;
1089 /* BRASL */
1090 if (op2 == 5)
1091 is_bras = 1;
1092 break;
1093 case 0xc4:
1094 case 0xc6:
1095 /* PC-relative addressing instructions. */
1096 mode = 2;
1097 break;
1098 case 0xc5: /* BPRP */
1099 case 0xc7: /* BPP */
1100 /* Branch prediction - just skip it. */
1101 return 0;
1102 case 0xcc:
1103 op2 = buf[1] & 0xf;
1104 /* BRCTH */
1105 if (op2 == 6)
1106 mode = 2;
1107 break;
1108 case 0xec:
1109 op2 = buf[5];
1110 switch (op2)
1112 case 0x44: /* BRXHG */
1113 case 0x45: /* BRXLG */
1114 case 0x64: /* CGRJ */
1115 case 0x65: /* CLGRJ */
1116 case 0x76: /* CRJ */
1117 case 0x77: /* CLRJ */
1118 mode = 1;
1119 break;
1121 break;
1124 if (mode != 0)
1126 /* We'll have to relocate an instruction with a PC-relative field.
1127 First, compute the target. */
1128 int64_t loffset = 0;
1129 CORE_ADDR target;
1130 if (mode == 1)
1132 int16_t soffset = 0;
1133 memcpy (&soffset, buf + 2, 2);
1134 loffset = soffset;
1136 else if (mode == 2)
1138 int32_t soffset = 0;
1139 memcpy (&soffset, buf + 2, 4);
1140 loffset = soffset;
1142 target = oldloc + loffset * 2;
1143 if (!is_64)
1144 target &= 0x7fffffff;
1146 if (is_bras)
1148 /* BRAS or BRASL was used. We cannot just relocate those, since
1149 they save the return address in a register. We can, however,
1150 replace them with a LARL+JG sequence. */
1152 /* Make the LARL. */
1153 int32_t soffset;
1154 buf[0] = 0xc0;
1155 buf[1] &= 0xf0;
1156 loffset = oldloc + ilen - *to;
1157 loffset >>= 1;
1158 soffset = loffset;
1159 if (soffset != loffset && is_64)
1160 return 1;
1161 memcpy (buf + 2, &soffset, 4);
1162 append_insns (to, 6, buf);
1164 /* Note: this is not fully correct. In 31-bit mode, LARL will write
1165 an address with the top bit 0, while BRAS/BRASL will write it
1166 with top bit 1. It should not matter much, since linux compilers
1167 use BR and not BSM to return from functions, but it could confuse
1168 some poor stack unwinder. */
1170 /* We'll now be writing a JG. */
1171 mode = 2;
1172 buf[0] = 0xc0;
1173 buf[1] = 0xf4;
1174 ilen = 6;
1177 /* Compute the new offset and write it to the buffer. */
1178 loffset = target - *to;
1179 loffset >>= 1;
1181 if (mode == 1)
1183 int16_t soffset = loffset;
1184 if (soffset != loffset)
1185 return 1;
1186 memcpy (buf + 2, &soffset, 2);
1188 else if (mode == 2)
1190 int32_t soffset = loffset;
1191 if (soffset != loffset && is_64)
1192 return 1;
1193 memcpy (buf + 2, &soffset, 4);
1196 append_insns (to, ilen, buf);
1197 return 0;
1200 /* Implementation of linux_target_ops method
1201 "install_fast_tracepoint_jump_pad". */
1203 static int
1204 s390_install_fast_tracepoint_jump_pad (CORE_ADDR tpoint,
1205 CORE_ADDR tpaddr,
1206 CORE_ADDR collector,
1207 CORE_ADDR lockaddr,
1208 ULONGEST orig_size,
1209 CORE_ADDR *jump_entry,
1210 CORE_ADDR *trampoline,
1211 ULONGEST *trampoline_size,
1212 unsigned char *jjump_pad_insn,
1213 ULONGEST *jjump_pad_insn_size,
1214 CORE_ADDR *adjusted_insn_addr,
1215 CORE_ADDR *adjusted_insn_addr_end,
1216 char *err)
1218 int i;
1219 int64_t loffset;
1220 int32_t offset;
1221 unsigned char jbuf[6] = { 0xc0, 0xf4, 0, 0, 0, 0 }; /* jg ... */
1222 CORE_ADDR buildaddr = *jump_entry;
1223 #ifdef __s390x__
1224 struct regcache *regcache = get_thread_regcache (current_thread, 0);
1225 int is_64 = register_size (regcache->tdesc, 0) == 8;
1226 int is_zarch = is_64 || have_hwcap_s390_high_gprs;
1227 int has_vx = have_hwcap_s390_vx;
1228 #else
1229 int is_64 = 0, is_zarch = 0, has_vx = 0;
1230 #endif
1231 CORE_ADDR literals[4] = {
1232 tpaddr,
1233 tpoint,
1234 collector,
1235 lockaddr,
1238 /* First, store the GPRs. */
1239 if (is_zarch)
1240 append_insns (&buildaddr, sizeof s390_ft_entry_gpr_zarch,
1241 s390_ft_entry_gpr_zarch);
1242 else
1243 append_insns (&buildaddr, sizeof s390_ft_entry_gpr_esa,
1244 s390_ft_entry_gpr_esa);
1246 /* Second, misc registers (ARs, PSWM, FPC). PSWA will be stored below. */
1247 append_insns (&buildaddr, sizeof s390_ft_entry_misc, s390_ft_entry_misc);
1249 /* Third, FRs or VRs. */
1250 if (has_vx)
1251 append_insns (&buildaddr, sizeof s390_ft_entry_vr, s390_ft_entry_vr);
1252 else
1253 append_insns (&buildaddr, sizeof s390_ft_entry_fr, s390_ft_entry_fr);
1255 /* Now, the main part of code - store PSWA, take lock, call collector,
1256 leave lock. First, we'll need to fetch 4 literals. */
1257 if (is_64) {
1258 unsigned char buf[] = {
1259 0x07, 0x07, /* nopr %r7 */
1260 0x07, 0x07, /* nopr %r7 */
1261 0x07, 0x07, /* nopr %r7 */
1262 0xa7, 0x15, 0x00, 0x12, /* bras %r1, .Lend */
1263 0, 0, 0, 0, 0, 0, 0, 0, /* tpaddr */
1264 0, 0, 0, 0, 0, 0, 0, 0, /* tpoint */
1265 0, 0, 0, 0, 0, 0, 0, 0, /* collector */
1266 0, 0, 0, 0, 0, 0, 0, 0, /* lockaddr */
1267 /* .Lend: */
1269 /* Find the proper start place in buf, so that literals will be
1270 aligned. */
1271 int bufpos = (buildaddr + 2) & 7;
1272 /* Stuff the literals into the buffer. */
1273 for (i = 0; i < 4; i++) {
1274 uint64_t lit = literals[i];
1275 memcpy (&buf[sizeof buf - 32 + i * 8], &lit, 8);
1277 append_insns (&buildaddr, sizeof buf - bufpos, buf + bufpos);
1278 append_insns (&buildaddr, sizeof s390_ft_main_64, s390_ft_main_64);
1279 } else {
1280 unsigned char buf[] = {
1281 0x07, 0x07, /* nopr %r7 */
1282 0xa7, 0x15, 0x00, 0x0a, /* bras %r1, .Lend */
1283 0, 0, 0, 0, /* tpaddr */
1284 0, 0, 0, 0, /* tpoint */
1285 0, 0, 0, 0, /* collector */
1286 0, 0, 0, 0, /* lockaddr */
1287 /* .Lend: */
1289 /* Find the proper start place in buf, so that literals will be
1290 aligned. */
1291 int bufpos = (buildaddr + 2) & 3;
1292 /* First literal will be saved as the PSWA, make sure it has the high bit
1293 set. */
1294 literals[0] |= 0x80000000;
1295 /* Stuff the literals into the buffer. */
1296 for (i = 0; i < 4; i++) {
1297 uint32_t lit = literals[i];
1298 memcpy (&buf[sizeof buf - 16 + i * 4], &lit, 4);
1300 append_insns (&buildaddr, sizeof buf - bufpos, buf + bufpos);
1301 append_insns (&buildaddr, sizeof s390_ft_main_31, s390_ft_main_31);
1304 /* Restore FRs or VRs. */
1305 if (has_vx)
1306 append_insns (&buildaddr, sizeof s390_ft_exit_vr, s390_ft_exit_vr);
1307 else
1308 append_insns (&buildaddr, sizeof s390_ft_exit_fr, s390_ft_exit_fr);
1310 /* Restore misc registers. */
1311 append_insns (&buildaddr, sizeof s390_ft_exit_misc, s390_ft_exit_misc);
1313 /* Restore the GPRs. */
1314 if (is_zarch)
1315 append_insns (&buildaddr, sizeof s390_ft_exit_gpr_zarch,
1316 s390_ft_exit_gpr_zarch);
1317 else
1318 append_insns (&buildaddr, sizeof s390_ft_exit_gpr_esa,
1319 s390_ft_exit_gpr_esa);
1321 /* Now, adjust the original instruction to execute in the jump
1322 pad. */
1323 *adjusted_insn_addr = buildaddr;
1324 if (s390_relocate_instruction (&buildaddr, tpaddr, is_64))
1326 sprintf (err, "E.Could not relocate instruction for tracepoint.");
1327 return 1;
1329 *adjusted_insn_addr_end = buildaddr;
1331 /* Finally, write a jump back to the program. */
1333 loffset = (tpaddr + orig_size) - buildaddr;
1334 loffset >>= 1;
1335 offset = loffset;
1336 if (is_64 && offset != loffset)
1338 sprintf (err,
1339 "E.Jump back from jump pad too far from tracepoint "
1340 "(offset 0x%" PRIx64 " > int33).", loffset);
1341 return 1;
1343 memcpy (jbuf + 2, &offset, 4);
1344 append_insns (&buildaddr, sizeof jbuf, jbuf);
1346 /* The jump pad is now built. Wire in a jump to our jump pad. This
1347 is always done last (by our caller actually), so that we can
1348 install fast tracepoints with threads running. This relies on
1349 the agent's atomic write support. */
1350 loffset = *jump_entry - tpaddr;
1351 loffset >>= 1;
1352 offset = loffset;
1353 if (is_64 && offset != loffset)
1355 sprintf (err,
1356 "E.Jump back from jump pad too far from tracepoint "
1357 "(offset 0x%" PRIx64 " > int33).", loffset);
1358 return 1;
1360 memcpy (jbuf + 2, &offset, 4);
1361 memcpy (jjump_pad_insn, jbuf, sizeof jbuf);
1362 *jjump_pad_insn_size = sizeof jbuf;
1364 /* Return the end address of our pad. */
1365 *jump_entry = buildaddr;
1367 return 0;
1370 /* Implementation of linux_target_ops method
1371 "get_min_fast_tracepoint_insn_len". */
1373 static int
1374 s390_get_min_fast_tracepoint_insn_len (void)
1376 /* We only support using 6-byte jumps to reach the tracepoint code.
1377 If the tracepoint buffer were allocated sufficiently close (64kiB)
1378 to the executable code, and the traced instruction itself was close
1379 enough to the beginning, we could use 4-byte jumps, but this doesn't
1380 seem to be worth the effort. */
1381 return 6;
1384 /* Implementation of linux_target_ops method "get_ipa_tdesc_idx". */
1386 static int
1387 s390_get_ipa_tdesc_idx (void)
1389 struct regcache *regcache = get_thread_regcache (current_thread, 0);
1390 const struct target_desc *tdesc = regcache->tdesc;
1392 #ifdef __s390x__
1393 if (tdesc == tdesc_s390x_linux64)
1394 return S390_TDESC_64;
1395 if (tdesc == tdesc_s390x_linux64v1)
1396 return S390_TDESC_64V1;
1397 if (tdesc == tdesc_s390x_linux64v2)
1398 return S390_TDESC_64V2;
1399 if (tdesc == tdesc_s390x_te_linux64)
1400 return S390_TDESC_TE;
1401 if (tdesc == tdesc_s390x_vx_linux64)
1402 return S390_TDESC_VX;
1403 if (tdesc == tdesc_s390x_tevx_linux64)
1404 return S390_TDESC_TEVX;
1405 if (tdesc == tdesc_s390x_gs_linux64)
1406 return S390_TDESC_GS;
1407 #endif
1409 if (tdesc == tdesc_s390_linux32)
1410 return S390_TDESC_32;
1411 if (tdesc == tdesc_s390_linux32v1)
1412 return S390_TDESC_32V1;
1413 if (tdesc == tdesc_s390_linux32v2)
1414 return S390_TDESC_32V2;
1415 if (tdesc == tdesc_s390_linux64)
1416 return S390_TDESC_64;
1417 if (tdesc == tdesc_s390_linux64v1)
1418 return S390_TDESC_64V1;
1419 if (tdesc == tdesc_s390_linux64v2)
1420 return S390_TDESC_64V2;
1421 if (tdesc == tdesc_s390_te_linux64)
1422 return S390_TDESC_TE;
1423 if (tdesc == tdesc_s390_vx_linux64)
1424 return S390_TDESC_VX;
1425 if (tdesc == tdesc_s390_tevx_linux64)
1426 return S390_TDESC_TEVX;
1427 if (tdesc == tdesc_s390_gs_linux64)
1428 return S390_TDESC_GS;
1430 return 0;
1433 /* Appends given buffer to current_insn_ptr in the target. */
1435 static void
1436 add_insns (const unsigned char *start, int len)
1438 CORE_ADDR buildaddr = current_insn_ptr;
1440 if (debug_threads)
1441 debug_printf ("Adding %d bytes of insn at %s\n",
1442 len, paddress (buildaddr));
1444 append_insns (&buildaddr, len, start);
1445 current_insn_ptr = buildaddr;
1448 /* Register usage in emit:
1450 - %r0, %r1: temp
1451 - %r2: top of stack (high word for 31-bit)
1452 - %r3: low word of top of stack (for 31-bit)
1453 - %r4, %r5: temp
1454 - %r6, %r7, %r8: don't use
1455 - %r9: saved arg1
1456 - %r10: saved arg2
1457 - %r11: frame pointer
1458 - %r12: saved top of stack for void_call_2 (high word for 31-bit)
1459 - %r13: low word of saved top of stack (for 31-bit)
1460 - %r14: return address for calls
1461 - %r15: stack pointer
1465 /* The "emit_prologue" emit_ops method for s390. */
1467 static void
1468 s390_emit_prologue (void)
1470 static const unsigned char buf[] = {
1471 0x90, 0x9f, 0xf0, 0x24, /* stm %r9, %r15, 0x24(%r15) */
1472 0x18, 0x92, /* lr %r9, %r2 */
1473 0x18, 0xa3, /* lr %r10, %r3 */
1474 0x18, 0xbf, /* lr %r11, %r15 */
1476 add_insns (buf, sizeof buf);
1479 /* The "emit_epilogue" emit_ops method for s390. */
1481 static void
1482 s390_emit_epilogue (void)
1484 static const unsigned char buf[] = {
1485 0x90, 0x23, 0xa0, 0x00, /* stm %r2, %r3, 0(%r10) */
1486 0xa7, 0x28, 0x00, 0x00, /* lhi %r2, 0 */
1487 0x98, 0x9f, 0xb0, 0x24, /* lm %r9, %r15, 0x24(%r11) */
1488 0x07, 0xfe, /* br %r14 */
1490 add_insns (buf, sizeof buf);
1493 /* The "emit_add" emit_ops method for s390. */
1495 static void
1496 s390_emit_add (void)
1498 static const unsigned char buf[] = {
1499 0x5e, 0x30, 0xf0, 0x04, /* al %r3, 4(%r15) */
1500 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x98, /* al %r2, 0(%r15) */
1501 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1503 add_insns (buf, sizeof buf);
1506 /* The "emit_sub" emit_ops method for s390. */
1508 static void
1509 s390_emit_sub (void)
1511 static const unsigned char buf[] = {
1512 0x98, 0x45, 0xf0, 0x00, /* lm %r4, %r5, 0(%r15) */
1513 0x1f, 0x53, /* slr %r5, %r3 */
1514 0xb9, 0x99, 0x00, 0x42, /* slbr %r4, %r2 */
1515 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1516 0x18, 0x35, /* lr %r3, %r5 */
1517 0x18, 0x24, /* lr %r2, %r4 */
1519 add_insns (buf, sizeof buf);
1522 /* The "emit_mul" emit_ops method for s390. */
1524 static void
1525 s390_emit_mul (void)
1527 emit_error = 1;
1530 /* The "emit_lsh" emit_ops method for s390. */
1532 static void
1533 s390_emit_lsh (void)
1535 static const unsigned char buf[] = {
1536 0x18, 0x43, /* lr %r4, %r3 */
1537 0x98, 0x23, 0xf0, 0x00, /* lm %r2, %r3, 0(%r15) */
1538 0x8d, 0x20, 0x40, 0x00, /* sldl %r2, 0(%r4) */
1539 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1541 add_insns (buf, sizeof buf);
1544 /* The "emit_rsh_signed" emit_ops method for s390. */
1546 static void
1547 s390_emit_rsh_signed (void)
1549 static const unsigned char buf[] = {
1550 0x18, 0x43, /* lr %r4, %r3 */
1551 0x98, 0x23, 0xf0, 0x00, /* lm %r2, %r3, 0(%r15) */
1552 0x8e, 0x20, 0x40, 0x00, /* srda %r2, 0(%r4) */
1553 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1555 add_insns (buf, sizeof buf);
1558 /* The "emit_rsh_unsigned" emit_ops method for s390. */
1560 static void
1561 s390_emit_rsh_unsigned (void)
1563 static const unsigned char buf[] = {
1564 0x18, 0x43, /* lr %r4, %r3 */
1565 0x98, 0x23, 0xf0, 0x00, /* lm %r2, %r3, 0(%r15) */
1566 0x8c, 0x20, 0x40, 0x00, /* srdl %r2, 0(%r4) */
1567 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1569 add_insns (buf, sizeof buf);
1572 /* The "emit_ext" emit_ops method for s390. */
1574 static void
1575 s390_emit_ext (int arg)
1577 unsigned char buf[] = {
1578 0x8d, 0x20, 0x00, (unsigned char) (64 - arg), /* sldl %r2, <64-arg> */
1579 0x8e, 0x20, 0x00, (unsigned char) (64 - arg), /* srda %r2, <64-arg> */
1581 add_insns (buf, sizeof buf);
1584 /* The "emit_log_not" emit_ops method for s390. */
1586 static void
1587 s390_emit_log_not (void)
1589 static const unsigned char buf[] = {
1590 0x16, 0x23, /* or %r2, %r3 */
1591 0xa7, 0x28, 0x00, 0x00, /* lhi %r2, 0 */
1592 0xa7, 0x38, 0x00, 0x00, /* lhi %r3, 0 */
1593 0xa7, 0x74, 0x00, 0x04, /* jne .Lskip */
1594 0xa7, 0x38, 0x00, 0x01, /* lhi %r3, 1 */
1595 /* .Lskip: */
1597 add_insns (buf, sizeof buf);
1600 /* The "emit_bit_and" emit_ops method for s390. */
1602 static void
1603 s390_emit_bit_and (void)
1605 static const unsigned char buf[] = {
1606 0x54, 0x20, 0xf0, 0x00, /* n %r2, 0(%r15) */
1607 0x54, 0x30, 0xf0, 0x04, /* n %r3, 4(%r15) */
1608 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1610 add_insns (buf, sizeof buf);
1613 /* The "emit_bit_or" emit_ops method for s390. */
1615 static void
1616 s390_emit_bit_or (void)
1618 static const unsigned char buf[] = {
1619 0x56, 0x20, 0xf0, 0x00, /* o %r2, 0(%r15) */
1620 0x56, 0x30, 0xf0, 0x04, /* o %r3, 4(%r15) */
1621 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1623 add_insns (buf, sizeof buf);
1626 /* The "emit_bit_xor" emit_ops method for s390. */
1628 static void
1629 s390_emit_bit_xor (void)
1631 static const unsigned char buf[] = {
1632 0x57, 0x20, 0xf0, 0x00, /* x %r2, 0(%r15) */
1633 0x57, 0x30, 0xf0, 0x04, /* x %r3, 4(%r15) */
1634 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1636 add_insns (buf, sizeof buf);
1639 /* The "emit_bit_not" emit_ops method for s390. */
1641 static void
1642 s390_emit_bit_not (void)
1644 static const unsigned char buf[] = {
1645 0xa7, 0x48, 0xff, 0xff, /* lhi %r4, -1 */
1646 0x17, 0x24, /* xr %r2, %r4 */
1647 0x17, 0x34, /* xr %r3, %r4 */
1649 add_insns (buf, sizeof buf);
1652 /* The "emit_equal" emit_ops method for s390. */
1654 static void
1655 s390_emit_equal (void)
1657 s390_emit_bit_xor ();
1658 s390_emit_log_not ();
1661 /* The "emit_less_signed" emit_ops method for s390. */
1663 static void
1664 s390_emit_less_signed (void)
1666 static const unsigned char buf[] = {
1667 0x59, 0x20, 0xf0, 0x00, /* c %r2, 0(%r15) */
1668 0xa7, 0x24, 0x00, 0x0c, /* jh .Lless */
1669 0xa7, 0x44, 0x00, 0x06, /* jl .Lhigh */
1670 0x55, 0x30, 0xf0, 0x04, /* cl %r3, 4(%r15) */
1671 0xa7, 0x24, 0x00, 0x06, /* jh .Lless */
1672 /* .Lhigh: */
1673 0xa7, 0x38, 0x00, 0x00, /* lhi %r3, 0 */
1674 0xa7, 0xf4, 0x00, 0x04, /* j .Lend */
1675 /* .Lless: */
1676 0xa7, 0x38, 0x00, 0x01, /* lhi %r3, 1 */
1677 /* .Lend: */
1678 0xa7, 0x28, 0x00, 0x00, /* lhi %r2, 0 */
1679 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1681 add_insns (buf, sizeof buf);
1684 /* The "emit_less_unsigned" emit_ops method for s390. */
1686 static void
1687 s390_emit_less_unsigned (void)
1689 static const unsigned char buf[] = {
1690 0x55, 0x20, 0xf0, 0x00, /* cl %r2, 0(%r15) */
1691 0xa7, 0x24, 0x00, 0x0c, /* jh .Lless */
1692 0xa7, 0x44, 0x00, 0x06, /* jl .Lhigh */
1693 0x55, 0x30, 0xf0, 0x04, /* cl %r3, 4(%r15) */
1694 0xa7, 0x24, 0x00, 0x06, /* jh .Lless */
1695 /* .Lhigh: */
1696 0xa7, 0x38, 0x00, 0x00, /* lhi %r3, 0 */
1697 0xa7, 0xf4, 0x00, 0x04, /* j .Lend */
1698 /* .Lless: */
1699 0xa7, 0x38, 0x00, 0x01, /* lhi %r3, 1 */
1700 /* .Lend: */
1701 0xa7, 0x28, 0x00, 0x00, /* lhi %r2, 0 */
1702 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1704 add_insns (buf, sizeof buf);
1707 /* The "emit_ref" emit_ops method for s390. */
1709 static void
1710 s390_emit_ref (int size)
1712 static const unsigned char buf1[] = {
1713 0xa7, 0x28, 0x00, 0x00, /* lhi %r2, 0 */
1714 0x43, 0x30, 0x30, 0x00, /* ic %r3, 0(%r3) */
1716 static const unsigned char buf2[] = {
1717 0xa7, 0x28, 0x00, 0x00, /* lhi %r2, 0 */
1718 0x48, 0x30, 0x30, 0x00, /* lh %r3, 0(%r3) */
1720 static const unsigned char buf4[] = {
1721 0xa7, 0x28, 0x00, 0x00, /* lhi %r2, 0 */
1722 0x58, 0x30, 0x30, 0x00, /* l %r3, 0(%r3) */
1724 static const unsigned char buf8[] = {
1725 0x98, 0x23, 0x30, 0x00, /* lm %r2, %r3, 0(%r3) */
1727 switch (size)
1729 case 1:
1730 add_insns (buf1, sizeof buf1);
1731 break;
1732 case 2:
1733 add_insns (buf2, sizeof buf2);
1734 break;
1735 case 4:
1736 add_insns (buf4, sizeof buf4);
1737 break;
1738 case 8:
1739 add_insns (buf8, sizeof buf8);
1740 break;
1741 default:
1742 emit_error = 1;
1746 /* The "emit_if_goto" emit_ops method for s390. */
1748 static void
1749 s390_emit_if_goto (int *offset_p, int *size_p)
1751 static const unsigned char buf[] = {
1752 0x16, 0x23, /* or %r2, %r3 */
1753 0x98, 0x23, 0xf0, 0x00, /* lm %r2, %r3, 0(%r15) */
1754 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1755 0xc0, 0x74, 0x00, 0x00, 0x00, 0x00 /* jgne <fillme> */
1757 add_insns (buf, sizeof buf);
1758 if (offset_p)
1759 *offset_p = 12;
1760 if (size_p)
1761 *size_p = 4;
1764 /* The "emit_goto" emit_ops method for s390 and s390x. */
1766 static void
1767 s390_emit_goto (int *offset_p, int *size_p)
1769 static const unsigned char buf[] = {
1770 0xc0, 0xf4, 0x00, 0x00, 0x00, 0x00, /* jg <fillme> */
1772 add_insns (buf, sizeof buf);
1773 if (offset_p)
1774 *offset_p = 2;
1775 if (size_p)
1776 *size_p = 4;
1779 /* The "write_goto_address" emit_ops method for s390 and s390x. */
1781 static void
1782 s390_write_goto_address (CORE_ADDR from, CORE_ADDR to, int size)
1784 long diff = ((long) (to - (from - 2))) / 2;
1785 int sdiff = diff;
1786 unsigned char buf[sizeof sdiff];
1788 /* We're only doing 4-byte sizes at the moment. */
1789 if (size != sizeof sdiff || sdiff != diff)
1791 emit_error = 1;
1792 return;
1795 memcpy (buf, &sdiff, sizeof sdiff);
1796 write_inferior_memory (from, buf, sizeof sdiff);
1799 /* Preparation for emitting a literal pool of given size. Loads the address
1800 of the pool into %r1, and jumps over it. Called should emit the pool data
1801 immediately afterwards. Used for both s390 and s390x. */
1803 static void
1804 s390_emit_litpool (int size)
1806 static const unsigned char nop[] = {
1807 0x07, 0x07,
1809 unsigned char buf[] = {
1810 0xa7, 0x15, 0x00,
1811 (unsigned char) ((size + 4) / 2), /* bras %r1, .Lend+size */
1812 /* .Lend: */
1814 if (size == 4)
1816 /* buf needs to start at even halfword for litpool to be aligned */
1817 if (current_insn_ptr & 2)
1818 add_insns (nop, sizeof nop);
1820 else
1822 while ((current_insn_ptr & 6) != 4)
1823 add_insns (nop, sizeof nop);
1825 add_insns (buf, sizeof buf);
1828 /* The "emit_const" emit_ops method for s390. */
1830 static void
1831 s390_emit_const (LONGEST num)
1833 unsigned long long n = num;
1834 unsigned char buf_s[] = {
1835 /* lhi %r3, <num> */
1836 0xa7, 0x38,
1837 (unsigned char) (num >> 8), (unsigned char) num,
1838 /* xr %r2, %r2 */
1839 0x17, 0x22,
1841 static const unsigned char buf_l[] = {
1842 0x98, 0x23, 0x10, 0x00, /* lm %r2, %r3, 0(%r1) */
1844 if (num < 0x8000 && num >= 0)
1846 add_insns (buf_s, sizeof buf_s);
1848 else
1850 s390_emit_litpool (8);
1851 add_insns ((unsigned char *) &n, sizeof n);
1852 add_insns (buf_l, sizeof buf_l);
1856 /* The "emit_call" emit_ops method for s390. */
1858 static void
1859 s390_emit_call (CORE_ADDR fn)
1861 unsigned int n = fn;
1862 static const unsigned char buf[] = {
1863 0x58, 0x10, 0x10, 0x00, /* l %r1, 0(%r1) */
1864 0xa7, 0xfa, 0xff, 0xa0, /* ahi %r15, -0x60 */
1865 0x0d, 0xe1, /* basr %r14, %r1 */
1866 0xa7, 0xfa, 0x00, 0x60, /* ahi %r15, 0x60 */
1868 s390_emit_litpool (4);
1869 add_insns ((unsigned char *) &n, sizeof n);
1870 add_insns (buf, sizeof buf);
1873 /* The "emit_reg" emit_ops method for s390. */
1875 static void
1876 s390_emit_reg (int reg)
1878 unsigned char bufpre[] = {
1879 /* lr %r2, %r9 */
1880 0x18, 0x29,
1881 /* lhi %r3, <reg> */
1882 0xa7, 0x38, (unsigned char) (reg >> 8), (unsigned char) reg,
1884 add_insns (bufpre, sizeof bufpre);
1885 s390_emit_call (get_raw_reg_func_addr ());
1888 /* The "emit_pop" emit_ops method for s390. */
1890 static void
1891 s390_emit_pop (void)
1893 static const unsigned char buf[] = {
1894 0x98, 0x23, 0xf0, 0x00, /* lm %r2, %r3, 0(%r15) */
1895 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1897 add_insns (buf, sizeof buf);
1900 /* The "emit_stack_flush" emit_ops method for s390. */
1902 static void
1903 s390_emit_stack_flush (void)
1905 static const unsigned char buf[] = {
1906 0xa7, 0xfa, 0xff, 0xf8, /* ahi %r15, -8 */
1907 0x90, 0x23, 0xf0, 0x00, /* stm %r2, %r3, 0(%r15) */
1909 add_insns (buf, sizeof buf);
1912 /* The "emit_zero_ext" emit_ops method for s390. */
1914 static void
1915 s390_emit_zero_ext (int arg)
1917 unsigned char buf[] = {
1918 0x8d, 0x20, 0x00, (unsigned char) (64 - arg), /* sldl %r2, <64-arg> */
1919 0x8c, 0x20, 0x00, (unsigned char) (64 - arg), /* srdl %r2, <64-arg> */
1921 add_insns (buf, sizeof buf);
1924 /* The "emit_swap" emit_ops method for s390. */
1926 static void
1927 s390_emit_swap (void)
1929 static const unsigned char buf[] = {
1930 0x98, 0x45, 0xf0, 0x00, /* lm %r4, %r5, 0(%r15) */
1931 0x90, 0x23, 0xf0, 0x00, /* stm %r2, %r3, 0(%r15) */
1932 0x18, 0x24, /* lr %r2, %r4 */
1933 0x18, 0x35, /* lr %r3, %r5 */
1935 add_insns (buf, sizeof buf);
1938 /* The "emit_stack_adjust" emit_ops method for s390. */
1940 static void
1941 s390_emit_stack_adjust (int n)
1943 unsigned char buf[] = {
1944 /* ahi %r15, 8*n */
1945 0xa7, 0xfa,
1946 (unsigned char ) (n * 8 >> 8), (unsigned char) (n * 8),
1948 add_insns (buf, sizeof buf);
1951 /* Sets %r2 to a 32-bit constant. */
1953 static void
1954 s390_emit_set_r2 (int arg1)
1956 unsigned char buf_s[] = {
1957 /* lhi %r2, <arg1> */
1958 0xa7, 0x28, (unsigned char) (arg1 >> 8), (unsigned char) arg1,
1960 static const unsigned char buf_l[] = {
1961 0x58, 0x20, 0x10, 0x00, /* l %r2, 0(%r1) */
1963 if (arg1 < 0x8000 && arg1 >= -0x8000)
1965 add_insns (buf_s, sizeof buf_s);
1967 else
1969 s390_emit_litpool (4);
1970 add_insns ((unsigned char *) &arg1, sizeof arg1);
1971 add_insns (buf_l, sizeof buf_l);
1975 /* The "emit_int_call_1" emit_ops method for s390. */
1977 static void
1978 s390_emit_int_call_1 (CORE_ADDR fn, int arg1)
1980 /* FN's prototype is `LONGEST(*fn)(int)'. */
1981 s390_emit_set_r2 (arg1);
1982 s390_emit_call (fn);
1985 /* The "emit_void_call_2" emit_ops method for s390. */
1987 static void
1988 s390_emit_void_call_2 (CORE_ADDR fn, int arg1)
1990 /* FN's prototype is `void(*fn)(int,LONGEST)'. */
1991 static const unsigned char buf[] = {
1992 0x18, 0xc2, /* lr %r12, %r2 */
1993 0x18, 0xd3, /* lr %r13, %r3 */
1994 0x18, 0x43, /* lr %r4, %r3 */
1995 0x18, 0x32, /* lr %r3, %r2 */
1997 static const unsigned char buf2[] = {
1998 0x18, 0x2c, /* lr %r2, %r12 */
1999 0x18, 0x3d, /* lr %r3, %r13 */
2001 add_insns (buf, sizeof buf);
2002 s390_emit_set_r2 (arg1);
2003 s390_emit_call (fn);
2004 add_insns (buf2, sizeof buf2);
2007 /* The "emit_eq_goto" emit_ops method for s390. */
2009 static void
2010 s390_emit_eq_goto (int *offset_p, int *size_p)
2012 static const unsigned char buf[] = {
2013 0x57, 0x20, 0xf0, 0x00, /* x %r2, 0(%r15) */
2014 0x57, 0x30, 0xf0, 0x04, /* x %r3, 4(%r15) */
2015 0x16, 0x23, /* or %r2, %r3 */
2016 0x98, 0x23, 0xf0, 0x08, /* lm %r2, %r3, 8(%r15) */
2017 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2018 0xc0, 0x84, 0x00, 0x00, 0x00, 0x00, /* jge <fillme> */
2020 add_insns (buf, sizeof buf);
2021 if (offset_p)
2022 *offset_p = 20;
2023 if (size_p)
2024 *size_p = 4;
2027 /* The "emit_ne_goto" emit_ops method for s390. */
2029 static void
2030 s390_emit_ne_goto (int *offset_p, int *size_p)
2032 static const unsigned char buf[] = {
2033 0x57, 0x20, 0xf0, 0x00, /* x %r2, 0(%r15) */
2034 0x57, 0x30, 0xf0, 0x04, /* x %r3, 4(%r15) */
2035 0x16, 0x23, /* or %r2, %r3 */
2036 0x98, 0x23, 0xf0, 0x08, /* lm %r2, %r3, 8(%r15) */
2037 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2038 0xc0, 0x74, 0x00, 0x00, 0x00, 0x00, /* jgne <fillme> */
2040 add_insns (buf, sizeof buf);
2041 if (offset_p)
2042 *offset_p = 20;
2043 if (size_p)
2044 *size_p = 4;
2047 /* The "emit_lt_goto" emit_ops method for s390. */
2049 static void
2050 s390_emit_lt_goto (int *offset_p, int *size_p)
2052 static const unsigned char buf[] = {
2053 0x59, 0x20, 0xf0, 0x00, /* c %r2, 0(%r15) */
2054 0xa7, 0x24, 0x00, 0x0e, /* jh .Ltrue */
2055 0xa7, 0x44, 0x00, 0x06, /* jl .Lfalse */
2056 0x55, 0x30, 0xf0, 0x04, /* cl %r3, 4(%r15) */
2057 0xa7, 0x24, 0x00, 0x08, /* jh .Ltrue */
2058 /* .Lfalse: */
2059 0x98, 0x23, 0xf0, 0x08, /* lm %r2, %r3, 8(%r15) */
2060 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2061 0xa7, 0xf4, 0x00, 0x09, /* j .Lend */
2062 /* .Ltrue: */
2063 0x98, 0x23, 0xf0, 0x08, /* lm %r2, %r3, 8(%r15) */
2064 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2065 0xc0, 0xf4, 0x00, 0x00, 0x00, 0x00, /* jg <fillme> */
2066 /* .Lend: */
2068 add_insns (buf, sizeof buf);
2069 if (offset_p)
2070 *offset_p = 42;
2071 if (size_p)
2072 *size_p = 4;
2075 /* The "emit_le_goto" emit_ops method for s390. */
2077 static void
2078 s390_emit_le_goto (int *offset_p, int *size_p)
2080 static const unsigned char buf[] = {
2081 0x59, 0x20, 0xf0, 0x00, /* c %r2, 0(%r15) */
2082 0xa7, 0x24, 0x00, 0x0e, /* jh .Ltrue */
2083 0xa7, 0x44, 0x00, 0x06, /* jl .Lfalse */
2084 0x55, 0x30, 0xf0, 0x04, /* cl %r3, 4(%r15) */
2085 0xa7, 0xa4, 0x00, 0x08, /* jhe .Ltrue */
2086 /* .Lfalse: */
2087 0x98, 0x23, 0xf0, 0x08, /* lm %r2, %r3, 8(%r15) */
2088 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2089 0xa7, 0xf4, 0x00, 0x09, /* j .Lend */
2090 /* .Ltrue: */
2091 0x98, 0x23, 0xf0, 0x08, /* lm %r2, %r3, 8(%r15) */
2092 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2093 0xc0, 0xf4, 0x00, 0x00, 0x00, 0x00, /* jg <fillme> */
2094 /* .Lend: */
2096 add_insns (buf, sizeof buf);
2097 if (offset_p)
2098 *offset_p = 42;
2099 if (size_p)
2100 *size_p = 4;
2103 /* The "emit_gt_goto" emit_ops method for s390. */
2105 static void
2106 s390_emit_gt_goto (int *offset_p, int *size_p)
2108 static const unsigned char buf[] = {
2109 0x59, 0x20, 0xf0, 0x00, /* c %r2, 0(%r15) */
2110 0xa7, 0x44, 0x00, 0x0e, /* jl .Ltrue */
2111 0xa7, 0x24, 0x00, 0x06, /* jh .Lfalse */
2112 0x55, 0x30, 0xf0, 0x04, /* cl %r3, 4(%r15) */
2113 0xa7, 0x44, 0x00, 0x08, /* jl .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_ge_goto" emit_ops method for s390. */
2133 static void
2134 s390_emit_ge_goto (int *offset_p, int *size_p)
2136 static const unsigned char buf[] = {
2137 0x59, 0x20, 0xf0, 0x00, /* c %r2, 0(%r15) */
2138 0xa7, 0x44, 0x00, 0x0e, /* jl .Ltrue */
2139 0xa7, 0x24, 0x00, 0x06, /* jh .Lfalse */
2140 0x55, 0x30, 0xf0, 0x04, /* cl %r3, 4(%r15) */
2141 0xa7, 0xc4, 0x00, 0x08, /* jle .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_ops" structure for s390. Named _impl to avoid name
2160 collision with s390_emit_ops function. */
2162 static struct emit_ops s390_emit_ops_impl =
2164 s390_emit_prologue,
2165 s390_emit_epilogue,
2166 s390_emit_add,
2167 s390_emit_sub,
2168 s390_emit_mul,
2169 s390_emit_lsh,
2170 s390_emit_rsh_signed,
2171 s390_emit_rsh_unsigned,
2172 s390_emit_ext,
2173 s390_emit_log_not,
2174 s390_emit_bit_and,
2175 s390_emit_bit_or,
2176 s390_emit_bit_xor,
2177 s390_emit_bit_not,
2178 s390_emit_equal,
2179 s390_emit_less_signed,
2180 s390_emit_less_unsigned,
2181 s390_emit_ref,
2182 s390_emit_if_goto,
2183 s390_emit_goto,
2184 s390_write_goto_address,
2185 s390_emit_const,
2186 s390_emit_call,
2187 s390_emit_reg,
2188 s390_emit_pop,
2189 s390_emit_stack_flush,
2190 s390_emit_zero_ext,
2191 s390_emit_swap,
2192 s390_emit_stack_adjust,
2193 s390_emit_int_call_1,
2194 s390_emit_void_call_2,
2195 s390_emit_eq_goto,
2196 s390_emit_ne_goto,
2197 s390_emit_lt_goto,
2198 s390_emit_le_goto,
2199 s390_emit_gt_goto,
2200 s390_emit_ge_goto
2203 #ifdef __s390x__
2205 /* The "emit_prologue" emit_ops method for s390x. */
2207 static void
2208 s390x_emit_prologue (void)
2210 static const unsigned char buf[] = {
2211 0xeb, 0x9f, 0xf0, 0x48, 0x00, 0x24, /* stmg %r9, %r15, 0x48(%r15) */
2212 0xb9, 0x04, 0x00, 0x92, /* lgr %r9, %r2 */
2213 0xb9, 0x04, 0x00, 0xa3, /* lgr %r10, %r3 */
2214 0xb9, 0x04, 0x00, 0xbf, /* lgr %r11, %r15 */
2216 add_insns (buf, sizeof buf);
2219 /* The "emit_epilogue" emit_ops method for s390x. */
2221 static void
2222 s390x_emit_epilogue (void)
2224 static const unsigned char buf[] = {
2225 0xe3, 0x20, 0xa0, 0x00, 0x00, 0x24, /* stg %r2, 0(%r10) */
2226 0xa7, 0x29, 0x00, 0x00, /* lghi %r2, 0 */
2227 0xeb, 0x9f, 0xf0, 0x48, 0x00, 0x04, /* lmg %r9, %r15, 0x48(%r15) */
2228 0x07, 0xfe, /* br %r14 */
2230 add_insns (buf, sizeof buf);
2233 /* The "emit_add" emit_ops method for s390x. */
2235 static void
2236 s390x_emit_add (void)
2238 static const unsigned char buf[] = {
2239 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x0a, /* alg %r2, 0(%r15) */
2240 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
2242 add_insns (buf, sizeof buf);
2245 /* The "emit_sub" emit_ops method for s390x. */
2247 static void
2248 s390x_emit_sub (void)
2250 static const unsigned char buf[] = {
2251 0xe3, 0x30, 0xf0, 0x00, 0x00, 0x04, /* lg %r3, 0(%r15) */
2252 0xb9, 0x0b, 0x00, 0x32, /* slgr %r3, %r2 */
2253 0xb9, 0x04, 0x00, 0x23, /* lgr %r2, %r3 */
2254 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
2256 add_insns (buf, sizeof buf);
2259 /* The "emit_mul" emit_ops method for s390x. */
2261 static void
2262 s390x_emit_mul (void)
2264 emit_error = 1;
2267 /* The "emit_lsh" emit_ops method for s390x. */
2269 static void
2270 s390x_emit_lsh (void)
2272 static const unsigned char buf[] = {
2273 0xe3, 0x30, 0xf0, 0x00, 0x00, 0x04, /* lg %r3, 0(%r15) */
2274 0xeb, 0x23, 0x20, 0x00, 0x00, 0x0d, /* sllg %r2, %r3, 0(%r2) */
2275 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
2277 add_insns (buf, sizeof buf);
2280 /* The "emit_rsh_signed" emit_ops method for s390x. */
2282 static void
2283 s390x_emit_rsh_signed (void)
2285 static const unsigned char buf[] = {
2286 0xe3, 0x30, 0xf0, 0x00, 0x00, 0x04, /* lg %r3, 0(%r15) */
2287 0xeb, 0x23, 0x20, 0x00, 0x00, 0x0a, /* srag %r2, %r3, 0(%r2) */
2288 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
2290 add_insns (buf, sizeof buf);
2293 /* The "emit_rsh_unsigned" emit_ops method for s390x. */
2295 static void
2296 s390x_emit_rsh_unsigned (void)
2298 static const unsigned char buf[] = {
2299 0xe3, 0x30, 0xf0, 0x00, 0x00, 0x04, /* lg %r3, 0(%r15) */
2300 0xeb, 0x23, 0x20, 0x00, 0x00, 0x0c, /* srlg %r2, %r3, 0(%r2) */
2301 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
2303 add_insns (buf, sizeof buf);
2306 /* The "emit_ext" emit_ops method for s390x. */
2308 static void
2309 s390x_emit_ext (int arg)
2311 unsigned char buf[] = {
2312 /* sllg %r2, %r2, <64-arg> */
2313 0xeb, 0x22, 0x00, (unsigned char) (64 - arg), 0x00, 0x0d,
2314 /* srag %r2, %r2, <64-arg> */
2315 0xeb, 0x22, 0x00, (unsigned char) (64 - arg), 0x00, 0x0a,
2317 add_insns (buf, sizeof buf);
2320 /* The "emit_log_not" emit_ops method for s390x. */
2322 static void
2323 s390x_emit_log_not (void)
2325 static const unsigned char buf[] = {
2326 0xb9, 0x00, 0x00, 0x22, /* lpgr %r2, %r2 */
2327 0xa7, 0x2b, 0xff, 0xff, /* aghi %r2, -1 */
2328 0xeb, 0x22, 0x00, 0x3f, 0x00, 0x0c, /* srlg %r2, %r2, 63 */
2330 add_insns (buf, sizeof buf);
2333 /* The "emit_bit_and" emit_ops method for s390x. */
2335 static void
2336 s390x_emit_bit_and (void)
2338 static const unsigned char buf[] = {
2339 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x80, /* ng %r2, 0(%r15) */
2340 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
2342 add_insns (buf, sizeof buf);
2345 /* The "emit_bit_or" emit_ops method for s390x. */
2347 static void
2348 s390x_emit_bit_or (void)
2350 static const unsigned char buf[] = {
2351 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x81, /* og %r2, 0(%r15) */
2352 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
2354 add_insns (buf, sizeof buf);
2357 /* The "emit_bit_xor" emit_ops method for s390x. */
2359 static void
2360 s390x_emit_bit_xor (void)
2362 static const unsigned char buf[] = {
2363 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x82, /* xg %r2, 0(%r15) */
2364 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
2366 add_insns (buf, sizeof buf);
2369 /* The "emit_bit_not" emit_ops method for s390x. */
2371 static void
2372 s390x_emit_bit_not (void)
2374 static const unsigned char buf[] = {
2375 0xa7, 0x39, 0xff, 0xff, /* lghi %r3, -1 */
2376 0xb9, 0x82, 0x00, 0x23, /* xgr %r2, %r3 */
2378 add_insns (buf, sizeof buf);
2381 /* The "emit_equal" emit_ops method for s390x. */
2383 static void
2384 s390x_emit_equal (void)
2386 s390x_emit_bit_xor ();
2387 s390x_emit_log_not ();
2390 /* The "emit_less_signed" emit_ops method for s390x. */
2392 static void
2393 s390x_emit_less_signed (void)
2395 static const unsigned char buf[] = {
2396 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20, /* cg %r2, 0(%r15) */
2397 0xa7, 0x29, 0x00, 0x01, /* lghi %r2, 1 */
2398 0xa7, 0x24, 0x00, 0x04, /* jh .Lend */
2399 0xa7, 0x29, 0x00, 0x00, /* lghi %r2, 0 */
2400 /* .Lend: */
2401 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
2403 add_insns (buf, sizeof buf);
2406 /* The "emit_less_unsigned" emit_ops method for s390x. */
2408 static void
2409 s390x_emit_less_unsigned (void)
2411 static const unsigned char buf[] = {
2412 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x21, /* clg %r2, 0(%r15) */
2413 0xa7, 0x29, 0x00, 0x01, /* lghi %r2, 1 */
2414 0xa7, 0x24, 0x00, 0x04, /* jh .Lend */
2415 0xa7, 0x29, 0x00, 0x00, /* lghi %r2, 0 */
2416 /* .Lend: */
2417 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
2419 add_insns (buf, sizeof buf);
2422 /* The "emit_ref" emit_ops method for s390x. */
2424 static void
2425 s390x_emit_ref (int size)
2427 static const unsigned char buf1[] = {
2428 0xe3, 0x20, 0x20, 0x00, 0x00, 0x90, /* llgc %r2, 0(%r2) */
2430 static const unsigned char buf2[] = {
2431 0xe3, 0x20, 0x20, 0x00, 0x00, 0x91 /* llgh %r2, 0(%r2) */
2433 static const unsigned char buf4[] = {
2434 0xe3, 0x20, 0x20, 0x00, 0x00, 0x16, /* llgf %r2, 0(%r2) */
2436 static const unsigned char buf8[] = {
2437 0xe3, 0x20, 0x20, 0x00, 0x00, 0x04, /* lg %r2, 0(%r2) */
2439 switch (size)
2441 case 1:
2442 add_insns (buf1, sizeof buf1);
2443 break;
2444 case 2:
2445 add_insns (buf2, sizeof buf2);
2446 break;
2447 case 4:
2448 add_insns (buf4, sizeof buf4);
2449 break;
2450 case 8:
2451 add_insns (buf8, sizeof buf8);
2452 break;
2453 default:
2454 emit_error = 1;
2458 /* The "emit_if_goto" emit_ops method for s390x. */
2460 static void
2461 s390x_emit_if_goto (int *offset_p, int *size_p)
2463 static const unsigned char buf[] = {
2464 0xb9, 0x02, 0x00, 0x22, /* ltgr %r2, %r2 */
2465 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x04, /* lg %r2, 0(%r15) */
2466 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
2467 0xc0, 0x74, 0x00, 0x00, 0x00, 0x00, /* jgne <fillme> */
2469 add_insns (buf, sizeof buf);
2470 if (offset_p)
2471 *offset_p = 16;
2472 if (size_p)
2473 *size_p = 4;
2476 /* The "emit_const" emit_ops method for s390x. */
2478 static void
2479 s390x_emit_const (LONGEST num)
2481 unsigned long long n = num;
2482 unsigned char buf_s[] = {
2483 /* lghi %r2, <num> */
2484 0xa7, 0x29, (unsigned char) (num >> 8), (unsigned char) num,
2486 static const unsigned char buf_l[] = {
2487 0xe3, 0x20, 0x10, 0x00, 0x00, 0x04, /* lg %r2, 0(%r1) */
2489 if (num < 0x8000 && num >= -0x8000)
2491 add_insns (buf_s, sizeof buf_s);
2493 else
2495 s390_emit_litpool (8);
2496 add_insns ((unsigned char *) &n, sizeof n);
2497 add_insns (buf_l, sizeof buf_l);
2501 /* The "emit_call" emit_ops method for s390x. */
2503 static void
2504 s390x_emit_call (CORE_ADDR fn)
2506 unsigned long n = fn;
2507 static const unsigned char buf[] = {
2508 0xe3, 0x10, 0x10, 0x00, 0x00, 0x04, /* lg %r1, 0(%r1) */
2509 0xa7, 0xfb, 0xff, 0x60, /* aghi %r15, -0xa0 */
2510 0x0d, 0xe1, /* basr %r14, %r1 */
2511 0xa7, 0xfb, 0x00, 0xa0, /* aghi %r15, 0xa0 */
2513 s390_emit_litpool (8);
2514 add_insns ((unsigned char *) &n, sizeof n);
2515 add_insns (buf, sizeof buf);
2518 /* The "emit_reg" emit_ops method for s390x. */
2520 static void
2521 s390x_emit_reg (int reg)
2523 unsigned char buf[] = {
2524 /* lgr %r2, %r9 */
2525 0xb9, 0x04, 0x00, 0x29,
2526 /* lghi %r3, <reg> */
2527 0xa7, 0x39, (unsigned char) (reg >> 8), (unsigned char) reg,
2529 add_insns (buf, sizeof buf);
2530 s390x_emit_call (get_raw_reg_func_addr ());
2533 /* The "emit_pop" emit_ops method for s390x. */
2535 static void
2536 s390x_emit_pop (void)
2538 static const unsigned char buf[] = {
2539 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x04, /* lg %r2, 0(%r15) */
2540 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
2542 add_insns (buf, sizeof buf);
2545 /* The "emit_stack_flush" emit_ops method for s390x. */
2547 static void
2548 s390x_emit_stack_flush (void)
2550 static const unsigned char buf[] = {
2551 0xa7, 0xfb, 0xff, 0xf8, /* aghi %r15, -8 */
2552 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x24, /* stg %r2, 0(%r15) */
2554 add_insns (buf, sizeof buf);
2557 /* The "emit_zero_ext" emit_ops method for s390x. */
2559 static void
2560 s390x_emit_zero_ext (int arg)
2562 unsigned char buf[] = {
2563 /* sllg %r2, %r2, <64-arg> */
2564 0xeb, 0x22, 0x00, (unsigned char) (64 - arg), 0x00, 0x0d,
2565 /* srlg %r2, %r2, <64-arg> */
2566 0xeb, 0x22, 0x00, (unsigned char) (64 - arg), 0x00, 0x0c,
2568 add_insns (buf, sizeof buf);
2571 /* The "emit_swap" emit_ops method for s390x. */
2573 static void
2574 s390x_emit_swap (void)
2576 static const unsigned char buf[] = {
2577 0xe3, 0x30, 0xf0, 0x00, 0x00, 0x04, /* lg %r3, 0(%r15) */
2578 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x24, /* stg %r2, 0(%r15) */
2579 0xb9, 0x04, 0x00, 0x23, /* lgr %r2, %r3 */
2581 add_insns (buf, sizeof buf);
2584 /* The "emit_stack_adjust" emit_ops method for s390x. */
2586 static void
2587 s390x_emit_stack_adjust (int n)
2589 unsigned char buf[] = {
2590 /* aghi %r15, 8*n */
2591 0xa7, 0xfb,
2592 (unsigned char) (n * 8 >> 8), (unsigned char) (n * 8),
2594 add_insns (buf, sizeof buf);
2597 /* The "emit_int_call_1" emit_ops method for s390x. */
2599 static void
2600 s390x_emit_int_call_1 (CORE_ADDR fn, int arg1)
2602 /* FN's prototype is `LONGEST(*fn)(int)'. */
2603 s390x_emit_const (arg1);
2604 s390x_emit_call (fn);
2607 /* The "emit_void_call_2" emit_ops method for s390x. */
2609 static void
2610 s390x_emit_void_call_2 (CORE_ADDR fn, int arg1)
2612 /* FN's prototype is `void(*fn)(int,LONGEST)'. */
2613 static const unsigned char buf[] = {
2614 0xb9, 0x04, 0x00, 0x32, /* lgr %r3, %r2 */
2615 0xb9, 0x04, 0x00, 0xc2, /* lgr %r12, %r2 */
2617 static const unsigned char buf2[] = {
2618 0xb9, 0x04, 0x00, 0x2c, /* lgr %r2, %r12 */
2620 add_insns (buf, sizeof buf);
2621 s390x_emit_const (arg1);
2622 s390x_emit_call (fn);
2623 add_insns (buf2, sizeof buf2);
2626 /* The "emit_eq_goto" emit_ops method for s390x. */
2628 static void
2629 s390x_emit_eq_goto (int *offset_p, int *size_p)
2631 static const unsigned char buf[] = {
2632 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20, /* cg %r2, 0(%r15) */
2633 0xe3, 0x20, 0xf0, 0x08, 0x00, 0x04, /* lg %r2, 8(%r15) */
2634 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2635 0xc0, 0x84, 0x00, 0x00, 0x00, 0x00, /* jge <fillme> */
2637 add_insns (buf, sizeof buf);
2638 if (offset_p)
2639 *offset_p = 18;
2640 if (size_p)
2641 *size_p = 4;
2644 /* The "emit_ne_goto" emit_ops method for s390x. */
2646 static void
2647 s390x_emit_ne_goto (int *offset_p, int *size_p)
2649 static const unsigned char buf[] = {
2650 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20, /* cg %r2, 0(%r15) */
2651 0xe3, 0x20, 0xf0, 0x08, 0x00, 0x04, /* lg %r2, 8(%r15) */
2652 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2653 0xc0, 0x74, 0x00, 0x00, 0x00, 0x00, /* jgne <fillme> */
2655 add_insns (buf, sizeof buf);
2656 if (offset_p)
2657 *offset_p = 18;
2658 if (size_p)
2659 *size_p = 4;
2662 /* The "emit_lt_goto" emit_ops method for s390x. */
2664 static void
2665 s390x_emit_lt_goto (int *offset_p, int *size_p)
2667 static const unsigned char buf[] = {
2668 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20, /* cg %r2, 0(%r15) */
2669 0xe3, 0x20, 0xf0, 0x08, 0x00, 0x04, /* lg %r2, 8(%r15) */
2670 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2671 0xc0, 0x24, 0x00, 0x00, 0x00, 0x00, /* jgh <fillme> */
2673 add_insns (buf, sizeof buf);
2674 if (offset_p)
2675 *offset_p = 18;
2676 if (size_p)
2677 *size_p = 4;
2680 /* The "emit_le_goto" emit_ops method for s390x. */
2682 static void
2683 s390x_emit_le_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, 0xa4, 0x00, 0x00, 0x00, 0x00, /* jghe <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_gt_goto" emit_ops method for s390x. */
2700 static void
2701 s390x_emit_gt_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, 0x44, 0x00, 0x00, 0x00, 0x00, /* jgl <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_ge_goto" emit_ops method for s390x. */
2718 static void
2719 s390x_emit_ge_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, 0xc4, 0x00, 0x00, 0x00, 0x00, /* jgle <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_ops" structure for s390x. */
2736 static struct emit_ops s390x_emit_ops =
2738 s390x_emit_prologue,
2739 s390x_emit_epilogue,
2740 s390x_emit_add,
2741 s390x_emit_sub,
2742 s390x_emit_mul,
2743 s390x_emit_lsh,
2744 s390x_emit_rsh_signed,
2745 s390x_emit_rsh_unsigned,
2746 s390x_emit_ext,
2747 s390x_emit_log_not,
2748 s390x_emit_bit_and,
2749 s390x_emit_bit_or,
2750 s390x_emit_bit_xor,
2751 s390x_emit_bit_not,
2752 s390x_emit_equal,
2753 s390x_emit_less_signed,
2754 s390x_emit_less_unsigned,
2755 s390x_emit_ref,
2756 s390x_emit_if_goto,
2757 s390_emit_goto,
2758 s390_write_goto_address,
2759 s390x_emit_const,
2760 s390x_emit_call,
2761 s390x_emit_reg,
2762 s390x_emit_pop,
2763 s390x_emit_stack_flush,
2764 s390x_emit_zero_ext,
2765 s390x_emit_swap,
2766 s390x_emit_stack_adjust,
2767 s390x_emit_int_call_1,
2768 s390x_emit_void_call_2,
2769 s390x_emit_eq_goto,
2770 s390x_emit_ne_goto,
2771 s390x_emit_lt_goto,
2772 s390x_emit_le_goto,
2773 s390x_emit_gt_goto,
2774 s390x_emit_ge_goto
2776 #endif
2778 /* The "emit_ops" linux_target_ops method. */
2780 static struct emit_ops *
2781 s390_emit_ops (void)
2783 #ifdef __s390x__
2784 struct regcache *regcache = get_thread_regcache (current_thread, 0);
2786 if (register_size (regcache->tdesc, 0) == 8)
2787 return &s390x_emit_ops;
2788 else
2789 #endif
2790 return &s390_emit_ops_impl;
2793 struct linux_target_ops the_low_target = {
2794 s390_arch_setup,
2795 s390_regs_info,
2796 s390_cannot_fetch_register,
2797 s390_cannot_store_register,
2798 NULL, /* fetch_register */
2799 s390_get_pc,
2800 s390_set_pc,
2801 NULL, /* breakpoint_kind_from_pc */
2802 s390_sw_breakpoint_from_kind,
2803 NULL,
2804 s390_breakpoint_len,
2805 s390_breakpoint_at,
2806 s390_supports_z_point_type,
2807 NULL,
2808 NULL,
2809 NULL,
2810 NULL,
2811 s390_collect_ptrace_register,
2812 s390_supply_ptrace_register,
2813 NULL, /* siginfo_fixup */
2814 NULL, /* new_process */
2815 NULL, /* delete_process */
2816 NULL, /* new_thread */
2817 NULL, /* delete_thread */
2818 NULL, /* new_fork */
2819 NULL, /* prepare_to_resume */
2820 NULL, /* process_qsupported */
2821 s390_supports_tracepoints,
2822 s390_get_thread_area,
2823 s390_install_fast_tracepoint_jump_pad,
2824 s390_emit_ops,
2825 s390_get_min_fast_tracepoint_insn_len,
2826 NULL, /* supports_range_stepping */
2827 NULL, /* breakpoint_kind_from_current_state */
2828 s390_supports_hardware_single_step,
2829 NULL, /* get_syscall_trapinfo */
2830 s390_get_ipa_tdesc_idx,
2833 void
2834 initialize_low_arch (void)
2836 /* Initialize the Linux target descriptions. */
2838 init_registers_s390_linux32 ();
2839 init_registers_s390_linux32v1 ();
2840 init_registers_s390_linux32v2 ();
2841 init_registers_s390_linux64 ();
2842 init_registers_s390_linux64v1 ();
2843 init_registers_s390_linux64v2 ();
2844 init_registers_s390_te_linux64 ();
2845 init_registers_s390_vx_linux64 ();
2846 init_registers_s390_tevx_linux64 ();
2847 init_registers_s390_gs_linux64 ();
2848 #ifdef __s390x__
2849 init_registers_s390x_linux64 ();
2850 init_registers_s390x_linux64v1 ();
2851 init_registers_s390x_linux64v2 ();
2852 init_registers_s390x_te_linux64 ();
2853 init_registers_s390x_vx_linux64 ();
2854 init_registers_s390x_tevx_linux64 ();
2855 init_registers_s390x_gs_linux64 ();
2856 #endif
2858 initialize_regsets_info (&s390_regsets_info);
2859 initialize_regsets_info (&s390_regsets_info_3264);