1 /* GNU/Linux S/390 specific low level interface, for the remote server
3 Copyright (C) 2001-2020 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. */
23 #include "linux-low.h"
24 #include "elf/common.h"
26 #include "tracepoint.h"
28 #include <asm/ptrace.h>
29 #include "nat/gdb_ptrace.h"
34 #include "linux-s390-tdesc.h"
36 #ifndef HWCAP_S390_HIGH_GPRS
37 #define HWCAP_S390_HIGH_GPRS 512
41 #define HWCAP_S390_TE 1024
45 #define HWCAP_S390_VX 2048
49 #define HWCAP_S390_GS 16384
52 #define s390_num_regs 52
54 /* Linux target op definitions for the S/390 architecture. */
56 class s390_target
: public linux_process_target
60 const regs_info
*get_regs_info () override
;
62 const gdb_byte
*sw_breakpoint_from_kind (int kind
, int *size
) override
;
64 bool supports_z_point_type (char z_type
) override
;
66 bool supports_tracepoints () override
;
68 void low_collect_ptrace_register (regcache
*regcache
, int regno
,
71 void low_supply_ptrace_register (regcache
*regcache
, int regno
,
72 const char *buf
) override
;
76 void low_arch_setup () override
;
78 bool low_cannot_fetch_register (int regno
) override
;
80 bool low_cannot_store_register (int regno
) override
;
82 bool low_supports_breakpoints () override
;
84 CORE_ADDR
low_get_pc (regcache
*regcache
) override
;
86 void low_set_pc (regcache
*regcache
, CORE_ADDR newpc
) override
;
88 int low_decr_pc_after_break () override
;
90 bool low_breakpoint_at (CORE_ADDR pc
) override
;
93 /* The singleton target ops object. */
95 static s390_target the_s390_target
;
97 static int s390_regmap
[] = {
98 PT_PSWMASK
, PT_PSWADDR
,
100 PT_GPR0
, PT_GPR1
, PT_GPR2
, PT_GPR3
,
101 PT_GPR4
, PT_GPR5
, PT_GPR6
, PT_GPR7
,
102 PT_GPR8
, PT_GPR9
, PT_GPR10
, PT_GPR11
,
103 PT_GPR12
, PT_GPR13
, PT_GPR14
, PT_GPR15
,
105 PT_ACR0
, PT_ACR1
, PT_ACR2
, PT_ACR3
,
106 PT_ACR4
, PT_ACR5
, PT_ACR6
, PT_ACR7
,
107 PT_ACR8
, PT_ACR9
, PT_ACR10
, PT_ACR11
,
108 PT_ACR12
, PT_ACR13
, PT_ACR14
, PT_ACR15
,
113 PT_FPR0_HI
, PT_FPR1_HI
, PT_FPR2_HI
, PT_FPR3_HI
,
114 PT_FPR4_HI
, PT_FPR5_HI
, PT_FPR6_HI
, PT_FPR7_HI
,
115 PT_FPR8_HI
, PT_FPR9_HI
, PT_FPR10_HI
, PT_FPR11_HI
,
116 PT_FPR12_HI
, PT_FPR13_HI
, PT_FPR14_HI
, PT_FPR15_HI
,
118 PT_FPR0
, PT_FPR1
, PT_FPR2
, PT_FPR3
,
119 PT_FPR4
, PT_FPR5
, PT_FPR6
, PT_FPR7
,
120 PT_FPR8
, PT_FPR9
, PT_FPR10
, PT_FPR11
,
121 PT_FPR12
, PT_FPR13
, PT_FPR14
, PT_FPR15
,
127 #define s390_num_regs_3264 68
130 static int s390_regmap_3264
[] = {
131 PT_PSWMASK
, PT_PSWADDR
,
133 PT_GPR0
, PT_GPR0
, PT_GPR1
, PT_GPR1
,
134 PT_GPR2
, PT_GPR2
, PT_GPR3
, PT_GPR3
,
135 PT_GPR4
, PT_GPR4
, PT_GPR5
, PT_GPR5
,
136 PT_GPR6
, PT_GPR6
, PT_GPR7
, PT_GPR7
,
137 PT_GPR8
, PT_GPR8
, PT_GPR9
, PT_GPR9
,
138 PT_GPR10
, PT_GPR10
, PT_GPR11
, PT_GPR11
,
139 PT_GPR12
, PT_GPR12
, PT_GPR13
, PT_GPR13
,
140 PT_GPR14
, PT_GPR14
, PT_GPR15
, PT_GPR15
,
142 PT_ACR0
, PT_ACR1
, PT_ACR2
, PT_ACR3
,
143 PT_ACR4
, PT_ACR5
, PT_ACR6
, PT_ACR7
,
144 PT_ACR8
, PT_ACR9
, PT_ACR10
, PT_ACR11
,
145 PT_ACR12
, PT_ACR13
, PT_ACR14
, PT_ACR15
,
149 PT_FPR0
, PT_FPR1
, PT_FPR2
, PT_FPR3
,
150 PT_FPR4
, PT_FPR5
, PT_FPR6
, PT_FPR7
,
151 PT_FPR8
, PT_FPR9
, PT_FPR10
, PT_FPR11
,
152 PT_FPR12
, PT_FPR13
, PT_FPR14
, PT_FPR15
,
157 static int s390_regmap_3264
[] = {
158 PT_PSWMASK
, PT_PSWADDR
,
160 -1, PT_GPR0
, -1, PT_GPR1
,
161 -1, PT_GPR2
, -1, PT_GPR3
,
162 -1, PT_GPR4
, -1, PT_GPR5
,
163 -1, PT_GPR6
, -1, PT_GPR7
,
164 -1, PT_GPR8
, -1, PT_GPR9
,
165 -1, PT_GPR10
, -1, PT_GPR11
,
166 -1, PT_GPR12
, -1, PT_GPR13
,
167 -1, PT_GPR14
, -1, PT_GPR15
,
169 PT_ACR0
, PT_ACR1
, PT_ACR2
, PT_ACR3
,
170 PT_ACR4
, PT_ACR5
, PT_ACR6
, PT_ACR7
,
171 PT_ACR8
, PT_ACR9
, PT_ACR10
, PT_ACR11
,
172 PT_ACR12
, PT_ACR13
, PT_ACR14
, PT_ACR15
,
176 PT_FPR0_HI
, PT_FPR1_HI
, PT_FPR2_HI
, PT_FPR3_HI
,
177 PT_FPR4_HI
, PT_FPR5_HI
, PT_FPR6_HI
, PT_FPR7_HI
,
178 PT_FPR8_HI
, PT_FPR9_HI
, PT_FPR10_HI
, PT_FPR11_HI
,
179 PT_FPR12_HI
, PT_FPR13_HI
, PT_FPR14_HI
, PT_FPR15_HI
,
187 s390_target::low_cannot_fetch_register (int regno
)
193 s390_target::low_cannot_store_register (int regno
)
199 s390_target::low_collect_ptrace_register (regcache
*regcache
, int regno
,
202 int size
= register_size (regcache
->tdesc
, regno
);
203 const struct regs_info
*regs_info
= get_regs_info ();
204 struct usrregs_info
*usr
= regs_info
->usrregs
;
205 int regaddr
= usr
->regmap
[regno
];
207 if (size
< sizeof (long))
209 memset (buf
, 0, sizeof (long));
211 if ((regno
^ 1) < usr
->num_regs
212 && usr
->regmap
[regno
^ 1] == regaddr
)
214 collect_register (regcache
, regno
& ~1, buf
);
215 collect_register (regcache
, (regno
& ~1) + 1,
216 buf
+ sizeof (long) - size
);
218 else if (regaddr
== PT_PSWMASK
)
220 /* Convert 4-byte PSW mask to 8 bytes by clearing bit 12 and copying
221 the basic addressing mode bit from the PSW address. */
222 gdb_byte
*addr
= (gdb_byte
*) alloca (register_size (regcache
->tdesc
, regno
^ 1));
223 collect_register (regcache
, regno
, buf
);
224 collect_register (regcache
, regno
^ 1, addr
);
226 buf
[size
] |= (addr
[0] & 0x80);
228 else if (regaddr
== PT_PSWADDR
)
230 /* Convert 4-byte PSW address to 8 bytes by clearing the addressing
231 mode bit (which gets copied to the PSW mask instead). */
232 collect_register (regcache
, regno
, buf
+ sizeof (long) - size
);
233 buf
[sizeof (long) - size
] &= ~0x80;
235 else if ((regaddr
>= PT_GPR0
&& regaddr
<= PT_GPR15
)
236 || regaddr
== PT_ORIGGPR2
)
237 collect_register (regcache
, regno
, buf
+ sizeof (long) - size
);
239 collect_register (regcache
, regno
, buf
);
241 else if (regaddr
!= -1)
242 collect_register (regcache
, regno
, buf
);
246 s390_target::low_supply_ptrace_register (regcache
*regcache
, int regno
,
249 int size
= register_size (regcache
->tdesc
, regno
);
250 const struct regs_info
*regs_info
= get_regs_info ();
251 struct usrregs_info
*usr
= regs_info
->usrregs
;
252 int regaddr
= usr
->regmap
[regno
];
254 if (size
< sizeof (long))
256 if ((regno
^ 1) < usr
->num_regs
257 && usr
->regmap
[regno
^ 1] == regaddr
)
259 supply_register (regcache
, regno
& ~1, buf
);
260 supply_register (regcache
, (regno
& ~1) + 1,
261 buf
+ sizeof (long) - size
);
263 else if (regaddr
== PT_PSWMASK
)
265 /* Convert 8-byte PSW mask to 4 bytes by setting bit 12 and copying
266 the basic addressing mode into the PSW address. */
267 gdb_byte
*mask
= (gdb_byte
*) alloca (size
);
268 gdb_byte
*addr
= (gdb_byte
*) alloca (register_size (regcache
->tdesc
, regno
^ 1));
269 memcpy (mask
, buf
, size
);
271 supply_register (regcache
, regno
, mask
);
273 collect_register (regcache
, regno
^ 1, addr
);
275 addr
[0] |= (buf
[size
] & 0x80);
276 supply_register (regcache
, regno
^ 1, addr
);
278 else if (regaddr
== PT_PSWADDR
)
280 /* Convert 8-byte PSW address to 4 bytes by truncating, but
281 keeping the addressing mode bit (which was set from the mask). */
282 gdb_byte
*addr
= (gdb_byte
*) alloca (size
);
284 collect_register (regcache
, regno
, addr
);
285 amode
= addr
[0] & 0x80;
286 memcpy (addr
, buf
+ sizeof (long) - size
, size
);
289 supply_register (regcache
, regno
, addr
);
291 else if ((regaddr
>= PT_GPR0
&& regaddr
<= PT_GPR15
)
292 || regaddr
== PT_ORIGGPR2
)
293 supply_register (regcache
, regno
, buf
+ sizeof (long) - size
);
295 supply_register (regcache
, regno
, buf
);
297 else if (regaddr
!= -1)
298 supply_register (regcache
, regno
, buf
);
301 /* Provide only a fill function for the general register set. ps_lgetregs
302 will use this for NPTL support. */
305 s390_fill_gregset (struct regcache
*regcache
, void *buf
)
308 const struct regs_info
*regs_info
= the_linux_target
->get_regs_info ();
309 struct usrregs_info
*usr
= regs_info
->usrregs
;
311 for (i
= 0; i
< usr
->num_regs
; i
++)
313 if (usr
->regmap
[i
] < PT_PSWMASK
314 || usr
->regmap
[i
] > PT_ACR15
)
317 ((s390_target
*) the_linux_target
)->low_collect_ptrace_register
318 (regcache
, i
, (char *) buf
+ usr
->regmap
[i
]);
322 /* Fill and store functions for extended register sets. */
326 s390_fill_gprs_high (struct regcache
*regcache
, void *buf
)
328 int r0h
= find_regno (regcache
->tdesc
, "r0h");
331 for (i
= 0; i
< 16; i
++)
332 collect_register (regcache
, r0h
+ 2 * i
, (char *) buf
+ 4 * i
);
336 s390_store_gprs_high (struct regcache
*regcache
, const void *buf
)
338 int r0h
= find_regno (regcache
->tdesc
, "r0h");
341 for (i
= 0; i
< 16; i
++)
342 supply_register (regcache
, r0h
+ 2 * i
, (const char *) buf
+ 4 * i
);
347 s390_store_last_break (struct regcache
*regcache
, const void *buf
)
351 p
= (const char *) buf
+ 8 - register_size (regcache
->tdesc
, 0);
352 supply_register_by_name (regcache
, "last_break", p
);
356 s390_fill_system_call (struct regcache
*regcache
, void *buf
)
358 collect_register_by_name (regcache
, "system_call", buf
);
362 s390_store_system_call (struct regcache
*regcache
, const void *buf
)
364 supply_register_by_name (regcache
, "system_call", buf
);
368 s390_store_tdb (struct regcache
*regcache
, const void *buf
)
370 int tdb0
= find_regno (regcache
->tdesc
, "tdb0");
371 int tr0
= find_regno (regcache
->tdesc
, "tr0");
374 for (i
= 0; i
< 4; i
++)
375 supply_register (regcache
, tdb0
+ i
, (const char *) buf
+ 8 * i
);
377 for (i
= 0; i
< 16; i
++)
378 supply_register (regcache
, tr0
+ i
, (const char *) buf
+ 8 * (16 + i
));
382 s390_fill_vxrs_low (struct regcache
*regcache
, void *buf
)
384 int v0
= find_regno (regcache
->tdesc
, "v0l");
387 for (i
= 0; i
< 16; i
++)
388 collect_register (regcache
, v0
+ i
, (char *) buf
+ 8 * i
);
392 s390_store_vxrs_low (struct regcache
*regcache
, const void *buf
)
394 int v0
= find_regno (regcache
->tdesc
, "v0l");
397 for (i
= 0; i
< 16; i
++)
398 supply_register (regcache
, v0
+ i
, (const char *) buf
+ 8 * i
);
402 s390_fill_vxrs_high (struct regcache
*regcache
, void *buf
)
404 int v16
= find_regno (regcache
->tdesc
, "v16");
407 for (i
= 0; i
< 16; i
++)
408 collect_register (regcache
, v16
+ i
, (char *) buf
+ 16 * i
);
412 s390_store_vxrs_high (struct regcache
*regcache
, const void *buf
)
414 int v16
= find_regno (regcache
->tdesc
, "v16");
417 for (i
= 0; i
< 16; i
++)
418 supply_register (regcache
, v16
+ i
, (const char *) buf
+ 16 * i
);
422 s390_store_gs (struct regcache
*regcache
, const void *buf
)
424 int gsd
= find_regno (regcache
->tdesc
, "gsd");
427 for (i
= 0; i
< 3; i
++)
428 supply_register (regcache
, gsd
+ i
, (const char *) buf
+ 8 * (i
+ 1));
432 s390_store_gsbc (struct regcache
*regcache
, const void *buf
)
434 int bc_gsd
= find_regno (regcache
->tdesc
, "bc_gsd");
437 for (i
= 0; i
< 3; i
++)
438 supply_register (regcache
, bc_gsd
+ i
, (const char *) buf
+ 8 * (i
+ 1));
441 static struct regset_info s390_regsets
[] = {
442 { 0, 0, 0, 0, GENERAL_REGS
, s390_fill_gregset
, NULL
},
444 { PTRACE_GETREGSET
, PTRACE_SETREGSET
, NT_S390_HIGH_GPRS
, 0,
445 EXTENDED_REGS
, s390_fill_gprs_high
, s390_store_gprs_high
},
447 /* Last break address is read-only; no fill function. */
448 { PTRACE_GETREGSET
, -1, NT_S390_LAST_BREAK
, 0, EXTENDED_REGS
,
449 NULL
, s390_store_last_break
},
450 { PTRACE_GETREGSET
, PTRACE_SETREGSET
, NT_S390_SYSTEM_CALL
, 0,
451 EXTENDED_REGS
, s390_fill_system_call
, s390_store_system_call
},
452 /* TDB is read-only. */
453 { PTRACE_GETREGSET
, -1, NT_S390_TDB
, 0, EXTENDED_REGS
,
454 NULL
, s390_store_tdb
},
455 { PTRACE_GETREGSET
, PTRACE_SETREGSET
, NT_S390_VXRS_LOW
, 0,
456 EXTENDED_REGS
, s390_fill_vxrs_low
, s390_store_vxrs_low
},
457 { PTRACE_GETREGSET
, PTRACE_SETREGSET
, NT_S390_VXRS_HIGH
, 0,
458 EXTENDED_REGS
, s390_fill_vxrs_high
, s390_store_vxrs_high
},
459 /* Guarded storage registers are read-only. */
460 { PTRACE_GETREGSET
, -1, NT_S390_GS_CB
, 0, EXTENDED_REGS
,
461 NULL
, s390_store_gs
},
462 { PTRACE_GETREGSET
, -1, NT_S390_GS_BC
, 0, EXTENDED_REGS
,
463 NULL
, s390_store_gsbc
},
468 static const gdb_byte s390_breakpoint
[] = { 0, 1 };
469 #define s390_breakpoint_len 2
471 /* Implementation of target ops method "sw_breakpoint_from_kind". */
474 s390_target::sw_breakpoint_from_kind (int kind
, int *size
)
476 *size
= s390_breakpoint_len
;
477 return s390_breakpoint
;
481 s390_target::low_supports_breakpoints ()
487 s390_target::low_get_pc (regcache
*regcache
)
489 if (register_size (regcache
->tdesc
, 0) == 4)
492 collect_register_by_name (regcache
, "pswa", &pswa
);
493 return pswa
& 0x7fffffff;
498 collect_register_by_name (regcache
, "pswa", &pc
);
504 s390_target::low_set_pc (regcache
*regcache
, CORE_ADDR newpc
)
506 if (register_size (regcache
->tdesc
, 0) == 4)
509 collect_register_by_name (regcache
, "pswa", &pswa
);
510 pswa
= (pswa
& 0x80000000) | (newpc
& 0x7fffffff);
511 supply_register_by_name (regcache
, "pswa", &pswa
);
515 unsigned long pc
= newpc
;
516 supply_register_by_name (regcache
, "pswa", &pc
);
521 s390_target::low_decr_pc_after_break ()
523 return s390_breakpoint_len
;
526 /* Determine the word size for the given PID, in bytes. */
530 s390_get_wordsize (int pid
)
533 PTRACE_XFER_TYPE pswm
= ptrace (PTRACE_PEEKUSER
, pid
,
534 (PTRACE_TYPE_ARG3
) 0,
535 (PTRACE_TYPE_ARG4
) 0);
538 warning (_("Couldn't determine word size, assuming 64-bit."));
541 /* Derive word size from extended addressing mode (PSW bit 31). */
542 return pswm
& (1L << 32) ? 8 : 4;
545 #define s390_get_wordsize(pid) 4
549 s390_check_regset (int pid
, int regset
, int regsize
)
551 void *buf
= alloca (regsize
);
555 iov
.iov_len
= regsize
;
557 if (ptrace (PTRACE_GETREGSET
, pid
, (long) regset
, (long) &iov
) >= 0
563 /* For a 31-bit inferior, whether the kernel supports using the full
565 static int have_hwcap_s390_high_gprs
= 0;
566 static int have_hwcap_s390_vx
= 0;
569 s390_target::low_arch_setup ()
571 const struct target_desc
*tdesc
;
572 struct regset_info
*regset
;
574 /* Determine word size and HWCAP. */
575 int pid
= pid_of (current_thread
);
576 int wordsize
= s390_get_wordsize (pid
);
577 unsigned long hwcap
= linux_get_hwcap (wordsize
);
579 /* Check whether the kernel supports extra register sets. */
580 int have_regset_last_break
581 = s390_check_regset (pid
, NT_S390_LAST_BREAK
, 8);
582 int have_regset_system_call
583 = s390_check_regset (pid
, NT_S390_SYSTEM_CALL
, 4);
585 = (s390_check_regset (pid
, NT_S390_TDB
, 256)
586 && (hwcap
& HWCAP_S390_TE
) != 0);
588 = (s390_check_regset (pid
, NT_S390_VXRS_LOW
, 128)
589 && s390_check_regset (pid
, NT_S390_VXRS_HIGH
, 256)
590 && (hwcap
& HWCAP_S390_VX
) != 0);
592 = (s390_check_regset (pid
, NT_S390_GS_CB
, 32)
593 && s390_check_regset (pid
, NT_S390_GS_BC
, 32)
594 && (hwcap
& HWCAP_S390_GS
) != 0);
601 tdesc
= tdesc_s390x_gs_linux64
;
602 else if (have_regset_vxrs
)
603 tdesc
= (have_regset_tdb
? tdesc_s390x_tevx_linux64
:
604 tdesc_s390x_vx_linux64
);
605 else if (have_regset_tdb
)
606 tdesc
= tdesc_s390x_te_linux64
;
607 else if (have_regset_system_call
)
608 tdesc
= tdesc_s390x_linux64v2
;
609 else if (have_regset_last_break
)
610 tdesc
= tdesc_s390x_linux64v1
;
612 tdesc
= tdesc_s390x_linux64
;
615 /* For a 31-bit inferior, check whether the kernel supports
616 using the full 64-bit GPRs. */
619 if (hwcap
& HWCAP_S390_HIGH_GPRS
)
621 have_hwcap_s390_high_gprs
= 1;
623 tdesc
= tdesc_s390_gs_linux64
;
624 else if (have_regset_vxrs
)
625 tdesc
= (have_regset_tdb
? tdesc_s390_tevx_linux64
:
626 tdesc_s390_vx_linux64
);
627 else if (have_regset_tdb
)
628 tdesc
= tdesc_s390_te_linux64
;
629 else if (have_regset_system_call
)
630 tdesc
= tdesc_s390_linux64v2
;
631 else if (have_regset_last_break
)
632 tdesc
= tdesc_s390_linux64v1
;
634 tdesc
= tdesc_s390_linux64
;
638 /* Assume 31-bit inferior process. */
639 if (have_regset_system_call
)
640 tdesc
= tdesc_s390_linux32v2
;
641 else if (have_regset_last_break
)
642 tdesc
= tdesc_s390_linux32v1
;
644 tdesc
= tdesc_s390_linux32
;
647 have_hwcap_s390_vx
= have_regset_vxrs
;
650 /* Update target_regsets according to available register sets. */
651 for (regset
= s390_regsets
; regset
->size
>= 0; regset
++)
652 if (regset
->get_request
== PTRACE_GETREGSET
)
653 switch (regset
->nt_type
)
656 case NT_S390_HIGH_GPRS
:
657 regset
->size
= have_hwcap_s390_high_gprs
? 64 : 0;
660 case NT_S390_LAST_BREAK
:
661 regset
->size
= have_regset_last_break
? 8 : 0;
663 case NT_S390_SYSTEM_CALL
:
664 regset
->size
= have_regset_system_call
? 4 : 0;
667 regset
->size
= have_regset_tdb
? 256 : 0;
669 case NT_S390_VXRS_LOW
:
670 regset
->size
= have_regset_vxrs
? 128 : 0;
672 case NT_S390_VXRS_HIGH
:
673 regset
->size
= have_regset_vxrs
? 256 : 0;
677 regset
->size
= have_regset_gs
? 32 : 0;
682 current_process ()->tdesc
= tdesc
;
687 s390_target::low_breakpoint_at (CORE_ADDR pc
)
689 unsigned char c
[s390_breakpoint_len
];
690 read_inferior_memory (pc
, c
, s390_breakpoint_len
);
691 return memcmp (c
, s390_breakpoint
, s390_breakpoint_len
) == 0;
694 /* Breakpoint/Watchpoint support. */
696 /* The "supports_z_point_type" target ops method. */
699 s390_target::supports_z_point_type (char z_type
)
710 /* Support for hardware single step. */
713 s390_supports_hardware_single_step (void)
718 static struct usrregs_info s390_usrregs_info
=
724 static struct regsets_info s390_regsets_info
=
726 s390_regsets
, /* regsets */
728 NULL
, /* disabled_regsets */
731 static struct regs_info myregs_info
=
733 NULL
, /* regset_bitmap */
738 static struct usrregs_info s390_usrregs_info_3264
=
744 static struct regsets_info s390_regsets_info_3264
=
746 s390_regsets
, /* regsets */
748 NULL
, /* disabled_regsets */
751 static struct regs_info regs_info_3264
=
753 NULL
, /* regset_bitmap */
754 &s390_usrregs_info_3264
,
755 &s390_regsets_info_3264
759 s390_target::get_regs_info ()
761 if (have_hwcap_s390_high_gprs
)
764 const struct target_desc
*tdesc
= current_process ()->tdesc
;
766 if (register_size (tdesc
, 0) == 4)
767 return ®s_info_3264
;
769 return ®s_info_3264
;
775 /* The "supports_tracepoints" target ops method. */
778 s390_target::supports_tracepoints ()
783 /* Implementation of linux_target_ops method "get_thread_area". */
786 s390_get_thread_area (int lwpid
, CORE_ADDR
*addrp
)
788 CORE_ADDR res
= ptrace (PTRACE_PEEKUSER
, lwpid
, (long) PT_ACR0
, (long) 0);
790 struct regcache
*regcache
= get_thread_regcache (current_thread
, 0);
792 if (register_size (regcache
->tdesc
, 0) == 4)
793 res
&= 0xffffffffull
;
800 /* Fast tracepoint support.
802 The register save area on stack is identical for all targets:
804 0x000+i*0x10: VR0-VR31
811 If we're on 31-bit linux, we just don't store the high parts of the GPRs.
812 Likewise, if there's no VX support, we just store the FRs into the slots
813 of low VR halves. The agent code is responsible for rearranging that
816 /* Code sequence saving GPRs for 31-bit target with no high GPRs. There's
817 one trick used at the very beginning: since there's no way to allocate
818 stack space without destroying CC (lay instruction can do it, but it's
819 only supported on later CPUs), we take 4 different execution paths for
820 every possible value of CC, allocate stack space, save %r0, stuff the
821 CC value in %r0 (shifted to match its position in PSWM high word),
822 then branch to common path. */
824 static const unsigned char s390_ft_entry_gpr_esa
[] = {
825 0xa7, 0x14, 0x00, 0x1e, /* jo .Lcc3 */
826 0xa7, 0x24, 0x00, 0x14, /* jh .Lcc2 */
827 0xa7, 0x44, 0x00, 0x0a, /* jl .Lcc1 */
829 0xa7, 0xfa, 0xfd, 0x00, /* ahi %r15, -0x300 */
830 0x50, 0x00, 0xf2, 0x04, /* st %r0, 0x204(%r15) */
831 0xa7, 0x08, 0x00, 0x00, /* lhi %r0, 0 */
832 0xa7, 0xf4, 0x00, 0x18, /* j .Lccdone */
834 0xa7, 0xfa, 0xfd, 0x00, /* ahi %r15, -0x300 */
835 0x50, 0x00, 0xf2, 0x04, /* st %r0, 0x204(%r15) */
836 0xa7, 0x08, 0x10, 0x00, /* lhi %r0, 0x1000 */
837 0xa7, 0xf4, 0x00, 0x10, /* j .Lccdone */
839 0xa7, 0xfa, 0xfd, 0x00, /* ahi %r15, -0x300 */
840 0x50, 0x00, 0xf2, 0x04, /* st %r0, 0x204(%r15) */
841 0xa7, 0x08, 0x20, 0x00, /* lhi %r0, 0x2000 */
842 0xa7, 0xf4, 0x00, 0x08, /* j .Lccdone */
844 0xa7, 0xfa, 0xfd, 0x00, /* ahi %r15, -0x300 */
845 0x50, 0x00, 0xf2, 0x04, /* st %r0, 0x204(%r15) */
846 0xa7, 0x08, 0x30, 0x00, /* lhi %r0, 0x3000 */
848 0x50, 0x10, 0xf2, 0x0c, /* st %r1, 0x20c(%r15) */
849 0x50, 0x20, 0xf2, 0x14, /* st %r2, 0x214(%r15) */
850 0x50, 0x30, 0xf2, 0x1c, /* st %r3, 0x21c(%r15) */
851 0x50, 0x40, 0xf2, 0x24, /* st %r4, 0x224(%r15) */
852 0x50, 0x50, 0xf2, 0x2c, /* st %r5, 0x22c(%r15) */
853 0x50, 0x60, 0xf2, 0x34, /* st %r6, 0x234(%r15) */
854 0x50, 0x70, 0xf2, 0x3c, /* st %r7, 0x23c(%r15) */
855 0x50, 0x80, 0xf2, 0x44, /* st %r8, 0x244(%r15) */
856 0x50, 0x90, 0xf2, 0x4c, /* st %r9, 0x24c(%r15) */
857 0x50, 0xa0, 0xf2, 0x54, /* st %r10, 0x254(%r15) */
858 0x50, 0xb0, 0xf2, 0x5c, /* st %r11, 0x25c(%r15) */
859 0x50, 0xc0, 0xf2, 0x64, /* st %r12, 0x264(%r15) */
860 0x50, 0xd0, 0xf2, 0x6c, /* st %r13, 0x26c(%r15) */
861 0x50, 0xe0, 0xf2, 0x74, /* st %r14, 0x274(%r15) */
862 /* Compute original value of %r15 and store it. We use ahi instead
863 of la to preserve the whole value, and not just the low 31 bits.
864 This is not particularly important here, but essential in the
865 zarch case where someone might be using the high word of %r15
866 as an extra register. */
867 0x18, 0x1f, /* lr %r1, %r15 */
868 0xa7, 0x1a, 0x03, 0x00, /* ahi %r1, 0x300 */
869 0x50, 0x10, 0xf2, 0x7c, /* st %r1, 0x27c(%r15) */
872 /* Code sequence saving GPRs for 31-bit target with high GPRs and for 64-bit
873 target. Same as above, except this time we can use load/store multiple,
874 since the 64-bit regs are tightly packed. */
876 static const unsigned char s390_ft_entry_gpr_zarch
[] = {
877 0xa7, 0x14, 0x00, 0x21, /* jo .Lcc3 */
878 0xa7, 0x24, 0x00, 0x16, /* jh .Lcc2 */
879 0xa7, 0x44, 0x00, 0x0b, /* jl .Lcc1 */
881 0xa7, 0xfb, 0xfd, 0x00, /* aghi %r15, -0x300 */
882 0xeb, 0x0e, 0xf2, 0x00, 0x00, 0x24, /* stmg %r0, %r14, 0x200(%r15) */
883 0xa7, 0x08, 0x00, 0x00, /* lhi %r0, 0 */
884 0xa7, 0xf4, 0x00, 0x1b, /* j .Lccdone */
886 0xa7, 0xfb, 0xfd, 0x00, /* aghi %r15, -0x300 */
887 0xeb, 0x0e, 0xf2, 0x00, 0x00, 0x24, /* stmg %r0, %r14, 0x200(%r15) */
888 0xa7, 0x08, 0x10, 0x00, /* lhi %r0, 0x1000 */
889 0xa7, 0xf4, 0x00, 0x12, /* j .Lccdone */
891 0xa7, 0xfb, 0xfd, 0x00, /* aghi %r15, -0x300 */
892 0xeb, 0x0e, 0xf2, 0x00, 0x00, 0x24, /* stmg %r0, %r14, 0x200(%r15) */
893 0xa7, 0x08, 0x20, 0x00, /* lhi %r0, 0x2000 */
894 0xa7, 0xf4, 0x00, 0x09, /* j .Lccdone */
896 0xa7, 0xfb, 0xfd, 0x00, /* aghi %r15, -0x300 */
897 0xeb, 0x0e, 0xf2, 0x00, 0x00, 0x24, /* stmg %r0, %r14, 0x200(%r15) */
898 0xa7, 0x08, 0x30, 0x00, /* lhi %r0, 0x3000 */
900 0xb9, 0x04, 0x00, 0x1f, /* lgr %r1, %r15 */
901 0xa7, 0x1b, 0x03, 0x00, /* aghi %r1, 0x300 */
902 0xe3, 0x10, 0xf2, 0x78, 0x00, 0x24, /* stg %r1, 0x278(%r15) */
905 /* Code sequence saving ARs, PSWM and FPC. PSWM has to be assembled from
906 current PSWM (read by epsw) and CC from entry (in %r0). */
908 static const unsigned char s390_ft_entry_misc
[] = {
909 0x9b, 0x0f, 0xf2, 0x80, /* stam %a0, %a15, 0x20(%%r15) */
910 0xb9, 0x8d, 0x00, 0x23, /* epsw %r2, %r3 */
911 0xa7, 0x18, 0xcf, 0xff, /* lhi %r1, ~0x3000 */
912 0x14, 0x21, /* nr %r2, %r1 */
913 0x16, 0x20, /* or %r2, %r0 */
914 0x50, 0x20, 0xf2, 0xc0, /* st %r2, 0x2c0(%r15) */
915 0x50, 0x30, 0xf2, 0xc4, /* st %r3, 0x2c4(%r15) */
916 0xb2, 0x9c, 0xf2, 0xd0, /* stfpc 0x2d0(%r15) */
919 /* Code sequence saving FRs, used if VX not supported. */
921 static const unsigned char s390_ft_entry_fr
[] = {
922 0x60, 0x00, 0xf0, 0x00, /* std %f0, 0x000(%r15) */
923 0x60, 0x10, 0xf0, 0x10, /* std %f1, 0x010(%r15) */
924 0x60, 0x20, 0xf0, 0x20, /* std %f2, 0x020(%r15) */
925 0x60, 0x30, 0xf0, 0x30, /* std %f3, 0x030(%r15) */
926 0x60, 0x40, 0xf0, 0x40, /* std %f4, 0x040(%r15) */
927 0x60, 0x50, 0xf0, 0x50, /* std %f5, 0x050(%r15) */
928 0x60, 0x60, 0xf0, 0x60, /* std %f6, 0x060(%r15) */
929 0x60, 0x70, 0xf0, 0x70, /* std %f7, 0x070(%r15) */
930 0x60, 0x80, 0xf0, 0x80, /* std %f8, 0x080(%r15) */
931 0x60, 0x90, 0xf0, 0x90, /* std %f9, 0x090(%r15) */
932 0x60, 0xa0, 0xf0, 0xa0, /* std %f10, 0x0a0(%r15) */
933 0x60, 0xb0, 0xf0, 0xb0, /* std %f11, 0x0b0(%r15) */
934 0x60, 0xc0, 0xf0, 0xc0, /* std %f12, 0x0c0(%r15) */
935 0x60, 0xd0, 0xf0, 0xd0, /* std %f13, 0x0d0(%r15) */
936 0x60, 0xe0, 0xf0, 0xe0, /* std %f14, 0x0e0(%r15) */
937 0x60, 0xf0, 0xf0, 0xf0, /* std %f15, 0x0f0(%r15) */
940 /* Code sequence saving VRs, used if VX not supported. */
942 static const unsigned char s390_ft_entry_vr
[] = {
943 0xe7, 0x0f, 0xf0, 0x00, 0x00, 0x3e, /* vstm %v0, %v15, 0x000(%r15) */
944 0xe7, 0x0f, 0xf1, 0x00, 0x0c, 0x3e, /* vstm %v16, %v31, 0x100(%r15) */
947 /* Code sequence doing the collection call for 31-bit target. %r1 contains
948 the address of the literal pool. */
950 static const unsigned char s390_ft_main_31
[] = {
951 /* Load the literals into registers. */
952 0x58, 0x50, 0x10, 0x00, /* l %r5, 0x0(%r1) */
953 0x58, 0x20, 0x10, 0x04, /* l %r2, 0x4(%r1) */
954 0x58, 0x40, 0x10, 0x08, /* l %r4, 0x8(%r1) */
955 0x58, 0x60, 0x10, 0x0c, /* l %r6, 0xc(%r1) */
956 /* Save original PSWA (tracepoint address | 0x80000000). */
957 0x50, 0x50, 0xf2, 0xcc, /* st %r5, 0x2cc(%r15) */
958 /* Construct a collecting_t object at %r15+0x2e0. */
959 0x50, 0x20, 0xf2, 0xe0, /* st %r2, 0x2e0(%r15) */
960 0x9b, 0x00, 0xf2, 0xe4, /* stam %a0, %a0, 0x2e4(%r15) */
961 /* Move its address to %r0. */
962 0x41, 0x00, 0xf2, 0xe0, /* la %r0, 0x2e0(%r15) */
965 0xa7, 0x18, 0x00, 0x00, /* lhi %r1, 0 */
966 0xba, 0x10, 0x60, 0x00, /* cs %r1, %r0, 0(%r6) */
967 0xa7, 0x74, 0xff, 0xfc, /* jne .Lloop */
968 /* Address of the register save block to %r3. */
969 0x18, 0x3f, /* lr %r3, %r15 */
970 /* Make a stack frame, so that we can call the collector. */
971 0xa7, 0xfa, 0xff, 0xa0, /* ahi %r15, -0x60 */
973 0x0d, 0xe4, /* basr %r14, %r4 */
974 /* And get rid of the stack frame again. */
975 0x41, 0xf0, 0xf0, 0x60, /* la %r15, 0x60(%r15) */
976 /* Leave the lock. */
977 0x07, 0xf0, /* br %r0 */
978 0xa7, 0x18, 0x00, 0x00, /* lhi %r1, 0 */
979 0x50, 0x10, 0x60, 0x00, /* st %t1, 0(%r6) */
982 /* Code sequence doing the collection call for 64-bit target. %r1 contains
983 the address of the literal pool. */
985 static const unsigned char s390_ft_main_64
[] = {
986 /* Load the literals into registers. */
987 0xe3, 0x50, 0x10, 0x00, 0x00, 0x04, /* lg %r5, 0x00(%r1) */
988 0xe3, 0x20, 0x10, 0x08, 0x00, 0x04, /* lg %r2, 0x08(%r1) */
989 0xe3, 0x40, 0x10, 0x10, 0x00, 0x04, /* lg %r4, 0x10(%r1) */
990 0xe3, 0x60, 0x10, 0x18, 0x00, 0x04, /* lg %r6, 0x18(%r1) */
991 /* Save original PSWA (tracepoint address). */
992 0xe3, 0x50, 0xf2, 0xc8, 0x00, 0x24, /* stg %r5, 0x2c8(%r15) */
993 /* Construct a collecting_t object at %r15+0x2e0. */
994 0xe3, 0x20, 0xf2, 0xe0, 0x00, 0x24, /* stg %r2, 0x2e0(%r15) */
995 0x9b, 0x01, 0xf2, 0xe8, /* stam %a0, %a1, 0x2e8(%r15) */
996 /* Move its address to %r0. */
997 0x41, 0x00, 0xf2, 0xe0, /* la %r0, 0x2e0(%r15) */
1000 0xa7, 0x19, 0x00, 0x00, /* lghi %r1, 0 */
1001 0xeb, 0x10, 0x60, 0x00, 0x00, 0x30, /* csg %r1, %r0, 0(%r6) */
1002 0xa7, 0x74, 0xff, 0xfb, /* jne .Lloop */
1003 /* Address of the register save block to %r3. */
1004 0xb9, 0x04, 0x00, 0x3f, /* lgr %r3, %r15 */
1005 /* Make a stack frame, so that we can call the collector. */
1006 0xa7, 0xfb, 0xff, 0x60, /* aghi %r15, -0xa0 */
1008 0x0d, 0xe4, /* basr %r14, %r4 */
1009 /* And get rid of the stack frame again. */
1010 0x41, 0xf0, 0xf0, 0xa0, /* la %r15, 0xa0(%r15) */
1011 /* Leave the lock. */
1012 0x07, 0xf0, /* br %r0 */
1013 0xa7, 0x19, 0x00, 0x00, /* lghi %r1, 0 */
1014 0xe3, 0x10, 0x60, 0x00, 0x00, 0x24, /* stg %t1, 0(%r6) */
1017 /* Code sequence restoring FRs, for targets with no VX support. */
1019 static const unsigned char s390_ft_exit_fr
[] = {
1020 0x68, 0x00, 0xf0, 0x00, /* ld %f0, 0x000(%r15) */
1021 0x68, 0x10, 0xf0, 0x10, /* ld %f1, 0x010(%r15) */
1022 0x68, 0x20, 0xf0, 0x20, /* ld %f2, 0x020(%r15) */
1023 0x68, 0x30, 0xf0, 0x30, /* ld %f3, 0x030(%r15) */
1024 0x68, 0x40, 0xf0, 0x40, /* ld %f4, 0x040(%r15) */
1025 0x68, 0x50, 0xf0, 0x50, /* ld %f5, 0x050(%r15) */
1026 0x68, 0x60, 0xf0, 0x60, /* ld %f6, 0x060(%r15) */
1027 0x68, 0x70, 0xf0, 0x70, /* ld %f7, 0x070(%r15) */
1028 0x68, 0x80, 0xf0, 0x80, /* ld %f8, 0x080(%r15) */
1029 0x68, 0x90, 0xf0, 0x90, /* ld %f9, 0x090(%r15) */
1030 0x68, 0xa0, 0xf0, 0xa0, /* ld %f10, 0x0a0(%r15) */
1031 0x68, 0xb0, 0xf0, 0xb0, /* ld %f11, 0x0b0(%r15) */
1032 0x68, 0xc0, 0xf0, 0xc0, /* ld %f12, 0x0c0(%r15) */
1033 0x68, 0xd0, 0xf0, 0xd0, /* ld %f13, 0x0d0(%r15) */
1034 0x68, 0xe0, 0xf0, 0xe0, /* ld %f14, 0x0e0(%r15) */
1035 0x68, 0xf0, 0xf0, 0xf0, /* ld %f15, 0x0f0(%r15) */
1038 /* Code sequence restoring VRs. */
1040 static const unsigned char s390_ft_exit_vr
[] = {
1041 0xe7, 0x0f, 0xf0, 0x00, 0x00, 0x36, /* vlm %v0, %v15, 0x000(%r15) */
1042 0xe7, 0x0f, 0xf1, 0x00, 0x0c, 0x36, /* vlm %v16, %v31, 0x100(%r15) */
1045 /* Code sequence restoring misc registers. As for PSWM, only CC should be
1046 modified by C code, so we use the alr instruction to restore it by
1047 manufacturing an operand that'll result in the original flags. */
1049 static const unsigned char s390_ft_exit_misc
[] = {
1050 0xb2, 0x9d, 0xf2, 0xd0, /* lfpc 0x2d0(%r15) */
1051 0x58, 0x00, 0xf2, 0xc0, /* l %r0, 0x2c0(%r15) */
1052 /* Extract CC to high 2 bits of %r0. */
1053 0x88, 0x00, 0x00, 0x0c, /* srl %r0, 12 */
1054 0x89, 0x00, 0x00, 0x1e, /* sll %r0, 30 */
1055 /* Add %r0 to itself. Result will be nonzero iff CC bit 0 is set, and
1056 will have carry iff CC bit 1 is set - resulting in the same flags
1058 0x1e, 0x00, /* alr %r0, %r0 */
1059 0x9a, 0x0f, 0xf2, 0x80, /* lam %a0, %a15, 0x280(%r15) */
1062 /* Code sequence restoring GPRs, for 31-bit targets with no high GPRs. */
1064 static const unsigned char s390_ft_exit_gpr_esa
[] = {
1065 0x58, 0x00, 0xf2, 0x04, /* l %r0, 0x204(%r15) */
1066 0x58, 0x10, 0xf2, 0x0c, /* l %r1, 0x20c(%r15) */
1067 0x58, 0x20, 0xf2, 0x14, /* l %r2, 0x214(%r15) */
1068 0x58, 0x30, 0xf2, 0x1c, /* l %r3, 0x21c(%r15) */
1069 0x58, 0x40, 0xf2, 0x24, /* l %r4, 0x224(%r15) */
1070 0x58, 0x50, 0xf2, 0x2c, /* l %r5, 0x22c(%r15) */
1071 0x58, 0x60, 0xf2, 0x34, /* l %r6, 0x234(%r15) */
1072 0x58, 0x70, 0xf2, 0x3c, /* l %r7, 0x23c(%r15) */
1073 0x58, 0x80, 0xf2, 0x44, /* l %r8, 0x244(%r15) */
1074 0x58, 0x90, 0xf2, 0x4c, /* l %r9, 0x24c(%r15) */
1075 0x58, 0xa0, 0xf2, 0x54, /* l %r10, 0x254(%r15) */
1076 0x58, 0xb0, 0xf2, 0x5c, /* l %r11, 0x25c(%r15) */
1077 0x58, 0xc0, 0xf2, 0x64, /* l %r12, 0x264(%r15) */
1078 0x58, 0xd0, 0xf2, 0x6c, /* l %r13, 0x26c(%r15) */
1079 0x58, 0xe0, 0xf2, 0x74, /* l %r14, 0x274(%r15) */
1080 0x58, 0xf0, 0xf2, 0x7c, /* l %r15, 0x27c(%r15) */
1083 /* Code sequence restoring GPRs, for 64-bit targets and 31-bit targets
1086 static const unsigned char s390_ft_exit_gpr_zarch
[] = {
1087 0xeb, 0x0f, 0xf2, 0x00, 0x00, 0x04, /* lmg %r0, %r15, 0x200(%r15) */
1090 /* Writes instructions to target, updating the to pointer. */
1093 append_insns (CORE_ADDR
*to
, size_t len
, const unsigned char *buf
)
1095 target_write_memory (*to
, buf
, len
);
1099 /* Relocates an instruction from oldloc to *to, updating to. */
1102 s390_relocate_instruction (CORE_ADDR
*to
, CORE_ADDR oldloc
, int is_64
)
1107 /* 0: no fixup, 1: PC16DBL fixup, 2: PC32DBL fixup. */
1110 read_inferior_memory (oldloc
, buf
, sizeof buf
);
1113 else if (buf
[0] < 0xc0)
1119 case 0x05: /* BALR */
1120 case 0x0c: /* BASSM */
1121 case 0x0d: /* BASR */
1122 case 0x45: /* BAL */
1123 case 0x4d: /* BAS */
1124 /* These save a return address and mess around with registers.
1125 We can't relocate them. */
1127 case 0x84: /* BRXH */
1128 case 0x85: /* BRXLE */
1133 /* BRC, BRAS, BRCT, BRCTG */
1134 if (op2
>= 4 && op2
<= 7)
1142 /* LARL, BRCL, BRASL */
1143 if (op2
== 0 || op2
== 4 || op2
== 5)
1151 /* PC-relative addressing instructions. */
1154 case 0xc5: /* BPRP */
1155 case 0xc7: /* BPP */
1156 /* Branch prediction - just skip it. */
1168 case 0x44: /* BRXHG */
1169 case 0x45: /* BRXLG */
1170 case 0x64: /* CGRJ */
1171 case 0x65: /* CLGRJ */
1172 case 0x76: /* CRJ */
1173 case 0x77: /* CLRJ */
1182 /* We'll have to relocate an instruction with a PC-relative field.
1183 First, compute the target. */
1184 int64_t loffset
= 0;
1188 int16_t soffset
= 0;
1189 memcpy (&soffset
, buf
+ 2, 2);
1194 int32_t soffset
= 0;
1195 memcpy (&soffset
, buf
+ 2, 4);
1198 target
= oldloc
+ loffset
* 2;
1200 target
&= 0x7fffffff;
1204 /* BRAS or BRASL was used. We cannot just relocate those, since
1205 they save the return address in a register. We can, however,
1206 replace them with a LARL+JG sequence. */
1208 /* Make the LARL. */
1212 loffset
= oldloc
+ ilen
- *to
;
1215 if (soffset
!= loffset
&& is_64
)
1217 memcpy (buf
+ 2, &soffset
, 4);
1218 append_insns (to
, 6, buf
);
1220 /* Note: this is not fully correct. In 31-bit mode, LARL will write
1221 an address with the top bit 0, while BRAS/BRASL will write it
1222 with top bit 1. It should not matter much, since linux compilers
1223 use BR and not BSM to return from functions, but it could confuse
1224 some poor stack unwinder. */
1226 /* We'll now be writing a JG. */
1233 /* Compute the new offset and write it to the buffer. */
1234 loffset
= target
- *to
;
1239 int16_t soffset
= loffset
;
1240 if (soffset
!= loffset
)
1242 memcpy (buf
+ 2, &soffset
, 2);
1246 int32_t soffset
= loffset
;
1247 if (soffset
!= loffset
&& is_64
)
1249 memcpy (buf
+ 2, &soffset
, 4);
1252 append_insns (to
, ilen
, buf
);
1256 /* Implementation of linux_target_ops method
1257 "install_fast_tracepoint_jump_pad". */
1260 s390_install_fast_tracepoint_jump_pad (CORE_ADDR tpoint
,
1262 CORE_ADDR collector
,
1265 CORE_ADDR
*jump_entry
,
1266 CORE_ADDR
*trampoline
,
1267 ULONGEST
*trampoline_size
,
1268 unsigned char *jjump_pad_insn
,
1269 ULONGEST
*jjump_pad_insn_size
,
1270 CORE_ADDR
*adjusted_insn_addr
,
1271 CORE_ADDR
*adjusted_insn_addr_end
,
1277 unsigned char jbuf
[6] = { 0xc0, 0xf4, 0, 0, 0, 0 }; /* jg ... */
1278 CORE_ADDR buildaddr
= *jump_entry
;
1280 struct regcache
*regcache
= get_thread_regcache (current_thread
, 0);
1281 int is_64
= register_size (regcache
->tdesc
, 0) == 8;
1282 int is_zarch
= is_64
|| have_hwcap_s390_high_gprs
;
1283 int has_vx
= have_hwcap_s390_vx
;
1285 int is_64
= 0, is_zarch
= 0, has_vx
= 0;
1287 CORE_ADDR literals
[4] = {
1294 /* First, store the GPRs. */
1296 append_insns (&buildaddr
, sizeof s390_ft_entry_gpr_zarch
,
1297 s390_ft_entry_gpr_zarch
);
1299 append_insns (&buildaddr
, sizeof s390_ft_entry_gpr_esa
,
1300 s390_ft_entry_gpr_esa
);
1302 /* Second, misc registers (ARs, PSWM, FPC). PSWA will be stored below. */
1303 append_insns (&buildaddr
, sizeof s390_ft_entry_misc
, s390_ft_entry_misc
);
1305 /* Third, FRs or VRs. */
1307 append_insns (&buildaddr
, sizeof s390_ft_entry_vr
, s390_ft_entry_vr
);
1309 append_insns (&buildaddr
, sizeof s390_ft_entry_fr
, s390_ft_entry_fr
);
1311 /* Now, the main part of code - store PSWA, take lock, call collector,
1312 leave lock. First, we'll need to fetch 4 literals. */
1314 unsigned char buf
[] = {
1315 0x07, 0x07, /* nopr %r7 */
1316 0x07, 0x07, /* nopr %r7 */
1317 0x07, 0x07, /* nopr %r7 */
1318 0xa7, 0x15, 0x00, 0x12, /* bras %r1, .Lend */
1319 0, 0, 0, 0, 0, 0, 0, 0, /* tpaddr */
1320 0, 0, 0, 0, 0, 0, 0, 0, /* tpoint */
1321 0, 0, 0, 0, 0, 0, 0, 0, /* collector */
1322 0, 0, 0, 0, 0, 0, 0, 0, /* lockaddr */
1325 /* Find the proper start place in buf, so that literals will be
1327 int bufpos
= (buildaddr
+ 2) & 7;
1328 /* Stuff the literals into the buffer. */
1329 for (i
= 0; i
< 4; i
++) {
1330 uint64_t lit
= literals
[i
];
1331 memcpy (&buf
[sizeof buf
- 32 + i
* 8], &lit
, 8);
1333 append_insns (&buildaddr
, sizeof buf
- bufpos
, buf
+ bufpos
);
1334 append_insns (&buildaddr
, sizeof s390_ft_main_64
, s390_ft_main_64
);
1336 unsigned char buf
[] = {
1337 0x07, 0x07, /* nopr %r7 */
1338 0xa7, 0x15, 0x00, 0x0a, /* bras %r1, .Lend */
1339 0, 0, 0, 0, /* tpaddr */
1340 0, 0, 0, 0, /* tpoint */
1341 0, 0, 0, 0, /* collector */
1342 0, 0, 0, 0, /* lockaddr */
1345 /* Find the proper start place in buf, so that literals will be
1347 int bufpos
= (buildaddr
+ 2) & 3;
1348 /* First literal will be saved as the PSWA, make sure it has the high bit
1350 literals
[0] |= 0x80000000;
1351 /* Stuff the literals into the buffer. */
1352 for (i
= 0; i
< 4; i
++) {
1353 uint32_t lit
= literals
[i
];
1354 memcpy (&buf
[sizeof buf
- 16 + i
* 4], &lit
, 4);
1356 append_insns (&buildaddr
, sizeof buf
- bufpos
, buf
+ bufpos
);
1357 append_insns (&buildaddr
, sizeof s390_ft_main_31
, s390_ft_main_31
);
1360 /* Restore FRs or VRs. */
1362 append_insns (&buildaddr
, sizeof s390_ft_exit_vr
, s390_ft_exit_vr
);
1364 append_insns (&buildaddr
, sizeof s390_ft_exit_fr
, s390_ft_exit_fr
);
1366 /* Restore misc registers. */
1367 append_insns (&buildaddr
, sizeof s390_ft_exit_misc
, s390_ft_exit_misc
);
1369 /* Restore the GPRs. */
1371 append_insns (&buildaddr
, sizeof s390_ft_exit_gpr_zarch
,
1372 s390_ft_exit_gpr_zarch
);
1374 append_insns (&buildaddr
, sizeof s390_ft_exit_gpr_esa
,
1375 s390_ft_exit_gpr_esa
);
1377 /* Now, adjust the original instruction to execute in the jump
1379 *adjusted_insn_addr
= buildaddr
;
1380 if (s390_relocate_instruction (&buildaddr
, tpaddr
, is_64
))
1382 sprintf (err
, "E.Could not relocate instruction for tracepoint.");
1385 *adjusted_insn_addr_end
= buildaddr
;
1387 /* Finally, write a jump back to the program. */
1389 loffset
= (tpaddr
+ orig_size
) - buildaddr
;
1392 if (is_64
&& offset
!= loffset
)
1395 "E.Jump back from jump pad too far from tracepoint "
1396 "(offset 0x%" PRIx64
" > int33).", loffset
);
1399 memcpy (jbuf
+ 2, &offset
, 4);
1400 append_insns (&buildaddr
, sizeof jbuf
, jbuf
);
1402 /* The jump pad is now built. Wire in a jump to our jump pad. This
1403 is always done last (by our caller actually), so that we can
1404 install fast tracepoints with threads running. This relies on
1405 the agent's atomic write support. */
1406 loffset
= *jump_entry
- tpaddr
;
1409 if (is_64
&& offset
!= loffset
)
1412 "E.Jump back from jump pad too far from tracepoint "
1413 "(offset 0x%" PRIx64
" > int33).", loffset
);
1416 memcpy (jbuf
+ 2, &offset
, 4);
1417 memcpy (jjump_pad_insn
, jbuf
, sizeof jbuf
);
1418 *jjump_pad_insn_size
= sizeof jbuf
;
1420 /* Return the end address of our pad. */
1421 *jump_entry
= buildaddr
;
1426 /* Implementation of linux_target_ops method
1427 "get_min_fast_tracepoint_insn_len". */
1430 s390_get_min_fast_tracepoint_insn_len (void)
1432 /* We only support using 6-byte jumps to reach the tracepoint code.
1433 If the tracepoint buffer were allocated sufficiently close (64kiB)
1434 to the executable code, and the traced instruction itself was close
1435 enough to the beginning, we could use 4-byte jumps, but this doesn't
1436 seem to be worth the effort. */
1440 /* Implementation of linux_target_ops method "get_ipa_tdesc_idx". */
1443 s390_get_ipa_tdesc_idx (void)
1445 struct regcache
*regcache
= get_thread_regcache (current_thread
, 0);
1446 const struct target_desc
*tdesc
= regcache
->tdesc
;
1449 if (tdesc
== tdesc_s390x_linux64
)
1450 return S390_TDESC_64
;
1451 if (tdesc
== tdesc_s390x_linux64v1
)
1452 return S390_TDESC_64V1
;
1453 if (tdesc
== tdesc_s390x_linux64v2
)
1454 return S390_TDESC_64V2
;
1455 if (tdesc
== tdesc_s390x_te_linux64
)
1456 return S390_TDESC_TE
;
1457 if (tdesc
== tdesc_s390x_vx_linux64
)
1458 return S390_TDESC_VX
;
1459 if (tdesc
== tdesc_s390x_tevx_linux64
)
1460 return S390_TDESC_TEVX
;
1461 if (tdesc
== tdesc_s390x_gs_linux64
)
1462 return S390_TDESC_GS
;
1465 if (tdesc
== tdesc_s390_linux32
)
1466 return S390_TDESC_32
;
1467 if (tdesc
== tdesc_s390_linux32v1
)
1468 return S390_TDESC_32V1
;
1469 if (tdesc
== tdesc_s390_linux32v2
)
1470 return S390_TDESC_32V2
;
1471 if (tdesc
== tdesc_s390_linux64
)
1472 return S390_TDESC_64
;
1473 if (tdesc
== tdesc_s390_linux64v1
)
1474 return S390_TDESC_64V1
;
1475 if (tdesc
== tdesc_s390_linux64v2
)
1476 return S390_TDESC_64V2
;
1477 if (tdesc
== tdesc_s390_te_linux64
)
1478 return S390_TDESC_TE
;
1479 if (tdesc
== tdesc_s390_vx_linux64
)
1480 return S390_TDESC_VX
;
1481 if (tdesc
== tdesc_s390_tevx_linux64
)
1482 return S390_TDESC_TEVX
;
1483 if (tdesc
== tdesc_s390_gs_linux64
)
1484 return S390_TDESC_GS
;
1489 /* Appends given buffer to current_insn_ptr in the target. */
1492 add_insns (const unsigned char *start
, int len
)
1494 CORE_ADDR buildaddr
= current_insn_ptr
;
1497 debug_printf ("Adding %d bytes of insn at %s\n",
1498 len
, paddress (buildaddr
));
1500 append_insns (&buildaddr
, len
, start
);
1501 current_insn_ptr
= buildaddr
;
1504 /* Register usage in emit:
1507 - %r2: top of stack (high word for 31-bit)
1508 - %r3: low word of top of stack (for 31-bit)
1510 - %r6, %r7, %r8: don't use
1513 - %r11: frame pointer
1514 - %r12: saved top of stack for void_call_2 (high word for 31-bit)
1515 - %r13: low word of saved top of stack (for 31-bit)
1516 - %r14: return address for calls
1517 - %r15: stack pointer
1521 /* The "emit_prologue" emit_ops method for s390. */
1524 s390_emit_prologue (void)
1526 static const unsigned char buf
[] = {
1527 0x90, 0x9f, 0xf0, 0x24, /* stm %r9, %r15, 0x24(%r15) */
1528 0x18, 0x92, /* lr %r9, %r2 */
1529 0x18, 0xa3, /* lr %r10, %r3 */
1530 0x18, 0xbf, /* lr %r11, %r15 */
1532 add_insns (buf
, sizeof buf
);
1535 /* The "emit_epilogue" emit_ops method for s390. */
1538 s390_emit_epilogue (void)
1540 static const unsigned char buf
[] = {
1541 0x90, 0x23, 0xa0, 0x00, /* stm %r2, %r3, 0(%r10) */
1542 0xa7, 0x28, 0x00, 0x00, /* lhi %r2, 0 */
1543 0x98, 0x9f, 0xb0, 0x24, /* lm %r9, %r15, 0x24(%r11) */
1544 0x07, 0xfe, /* br %r14 */
1546 add_insns (buf
, sizeof buf
);
1549 /* The "emit_add" emit_ops method for s390. */
1552 s390_emit_add (void)
1554 static const unsigned char buf
[] = {
1555 0x5e, 0x30, 0xf0, 0x04, /* al %r3, 4(%r15) */
1556 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x98, /* al %r2, 0(%r15) */
1557 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1559 add_insns (buf
, sizeof buf
);
1562 /* The "emit_sub" emit_ops method for s390. */
1565 s390_emit_sub (void)
1567 static const unsigned char buf
[] = {
1568 0x98, 0x45, 0xf0, 0x00, /* lm %r4, %r5, 0(%r15) */
1569 0x1f, 0x53, /* slr %r5, %r3 */
1570 0xb9, 0x99, 0x00, 0x42, /* slbr %r4, %r2 */
1571 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1572 0x18, 0x35, /* lr %r3, %r5 */
1573 0x18, 0x24, /* lr %r2, %r4 */
1575 add_insns (buf
, sizeof buf
);
1578 /* The "emit_mul" emit_ops method for s390. */
1581 s390_emit_mul (void)
1586 /* The "emit_lsh" emit_ops method for s390. */
1589 s390_emit_lsh (void)
1591 static const unsigned char buf
[] = {
1592 0x18, 0x43, /* lr %r4, %r3 */
1593 0x98, 0x23, 0xf0, 0x00, /* lm %r2, %r3, 0(%r15) */
1594 0x8d, 0x20, 0x40, 0x00, /* sldl %r2, 0(%r4) */
1595 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1597 add_insns (buf
, sizeof buf
);
1600 /* The "emit_rsh_signed" emit_ops method for s390. */
1603 s390_emit_rsh_signed (void)
1605 static const unsigned char buf
[] = {
1606 0x18, 0x43, /* lr %r4, %r3 */
1607 0x98, 0x23, 0xf0, 0x00, /* lm %r2, %r3, 0(%r15) */
1608 0x8e, 0x20, 0x40, 0x00, /* srda %r2, 0(%r4) */
1609 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1611 add_insns (buf
, sizeof buf
);
1614 /* The "emit_rsh_unsigned" emit_ops method for s390. */
1617 s390_emit_rsh_unsigned (void)
1619 static const unsigned char buf
[] = {
1620 0x18, 0x43, /* lr %r4, %r3 */
1621 0x98, 0x23, 0xf0, 0x00, /* lm %r2, %r3, 0(%r15) */
1622 0x8c, 0x20, 0x40, 0x00, /* srdl %r2, 0(%r4) */
1623 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1625 add_insns (buf
, sizeof buf
);
1628 /* The "emit_ext" emit_ops method for s390. */
1631 s390_emit_ext (int arg
)
1633 unsigned char buf
[] = {
1634 0x8d, 0x20, 0x00, (unsigned char) (64 - arg
), /* sldl %r2, <64-arg> */
1635 0x8e, 0x20, 0x00, (unsigned char) (64 - arg
), /* srda %r2, <64-arg> */
1637 add_insns (buf
, sizeof buf
);
1640 /* The "emit_log_not" emit_ops method for s390. */
1643 s390_emit_log_not (void)
1645 static const unsigned char buf
[] = {
1646 0x16, 0x23, /* or %r2, %r3 */
1647 0xa7, 0x28, 0x00, 0x00, /* lhi %r2, 0 */
1648 0xa7, 0x38, 0x00, 0x00, /* lhi %r3, 0 */
1649 0xa7, 0x74, 0x00, 0x04, /* jne .Lskip */
1650 0xa7, 0x38, 0x00, 0x01, /* lhi %r3, 1 */
1653 add_insns (buf
, sizeof buf
);
1656 /* The "emit_bit_and" emit_ops method for s390. */
1659 s390_emit_bit_and (void)
1661 static const unsigned char buf
[] = {
1662 0x54, 0x20, 0xf0, 0x00, /* n %r2, 0(%r15) */
1663 0x54, 0x30, 0xf0, 0x04, /* n %r3, 4(%r15) */
1664 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1666 add_insns (buf
, sizeof buf
);
1669 /* The "emit_bit_or" emit_ops method for s390. */
1672 s390_emit_bit_or (void)
1674 static const unsigned char buf
[] = {
1675 0x56, 0x20, 0xf0, 0x00, /* o %r2, 0(%r15) */
1676 0x56, 0x30, 0xf0, 0x04, /* o %r3, 4(%r15) */
1677 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1679 add_insns (buf
, sizeof buf
);
1682 /* The "emit_bit_xor" emit_ops method for s390. */
1685 s390_emit_bit_xor (void)
1687 static const unsigned char buf
[] = {
1688 0x57, 0x20, 0xf0, 0x00, /* x %r2, 0(%r15) */
1689 0x57, 0x30, 0xf0, 0x04, /* x %r3, 4(%r15) */
1690 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1692 add_insns (buf
, sizeof buf
);
1695 /* The "emit_bit_not" emit_ops method for s390. */
1698 s390_emit_bit_not (void)
1700 static const unsigned char buf
[] = {
1701 0xa7, 0x48, 0xff, 0xff, /* lhi %r4, -1 */
1702 0x17, 0x24, /* xr %r2, %r4 */
1703 0x17, 0x34, /* xr %r3, %r4 */
1705 add_insns (buf
, sizeof buf
);
1708 /* The "emit_equal" emit_ops method for s390. */
1711 s390_emit_equal (void)
1713 s390_emit_bit_xor ();
1714 s390_emit_log_not ();
1717 /* The "emit_less_signed" emit_ops method for s390. */
1720 s390_emit_less_signed (void)
1722 static const unsigned char buf
[] = {
1723 0x59, 0x20, 0xf0, 0x00, /* c %r2, 0(%r15) */
1724 0xa7, 0x24, 0x00, 0x0c, /* jh .Lless */
1725 0xa7, 0x44, 0x00, 0x06, /* jl .Lhigh */
1726 0x55, 0x30, 0xf0, 0x04, /* cl %r3, 4(%r15) */
1727 0xa7, 0x24, 0x00, 0x06, /* jh .Lless */
1729 0xa7, 0x38, 0x00, 0x00, /* lhi %r3, 0 */
1730 0xa7, 0xf4, 0x00, 0x04, /* j .Lend */
1732 0xa7, 0x38, 0x00, 0x01, /* lhi %r3, 1 */
1734 0xa7, 0x28, 0x00, 0x00, /* lhi %r2, 0 */
1735 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1737 add_insns (buf
, sizeof buf
);
1740 /* The "emit_less_unsigned" emit_ops method for s390. */
1743 s390_emit_less_unsigned (void)
1745 static const unsigned char buf
[] = {
1746 0x55, 0x20, 0xf0, 0x00, /* cl %r2, 0(%r15) */
1747 0xa7, 0x24, 0x00, 0x0c, /* jh .Lless */
1748 0xa7, 0x44, 0x00, 0x06, /* jl .Lhigh */
1749 0x55, 0x30, 0xf0, 0x04, /* cl %r3, 4(%r15) */
1750 0xa7, 0x24, 0x00, 0x06, /* jh .Lless */
1752 0xa7, 0x38, 0x00, 0x00, /* lhi %r3, 0 */
1753 0xa7, 0xf4, 0x00, 0x04, /* j .Lend */
1755 0xa7, 0x38, 0x00, 0x01, /* lhi %r3, 1 */
1757 0xa7, 0x28, 0x00, 0x00, /* lhi %r2, 0 */
1758 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1760 add_insns (buf
, sizeof buf
);
1763 /* The "emit_ref" emit_ops method for s390. */
1766 s390_emit_ref (int size
)
1768 static const unsigned char buf1
[] = {
1769 0xa7, 0x28, 0x00, 0x00, /* lhi %r2, 0 */
1770 0x43, 0x30, 0x30, 0x00, /* ic %r3, 0(%r3) */
1772 static const unsigned char buf2
[] = {
1773 0xa7, 0x28, 0x00, 0x00, /* lhi %r2, 0 */
1774 0x48, 0x30, 0x30, 0x00, /* lh %r3, 0(%r3) */
1776 static const unsigned char buf4
[] = {
1777 0xa7, 0x28, 0x00, 0x00, /* lhi %r2, 0 */
1778 0x58, 0x30, 0x30, 0x00, /* l %r3, 0(%r3) */
1780 static const unsigned char buf8
[] = {
1781 0x98, 0x23, 0x30, 0x00, /* lm %r2, %r3, 0(%r3) */
1786 add_insns (buf1
, sizeof buf1
);
1789 add_insns (buf2
, sizeof buf2
);
1792 add_insns (buf4
, sizeof buf4
);
1795 add_insns (buf8
, sizeof buf8
);
1802 /* The "emit_if_goto" emit_ops method for s390. */
1805 s390_emit_if_goto (int *offset_p
, int *size_p
)
1807 static const unsigned char buf
[] = {
1808 0x16, 0x23, /* or %r2, %r3 */
1809 0x98, 0x23, 0xf0, 0x00, /* lm %r2, %r3, 0(%r15) */
1810 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1811 0xc0, 0x74, 0x00, 0x00, 0x00, 0x00 /* jgne <fillme> */
1813 add_insns (buf
, sizeof buf
);
1820 /* The "emit_goto" emit_ops method for s390 and s390x. */
1823 s390_emit_goto (int *offset_p
, int *size_p
)
1825 static const unsigned char buf
[] = {
1826 0xc0, 0xf4, 0x00, 0x00, 0x00, 0x00, /* jg <fillme> */
1828 add_insns (buf
, sizeof buf
);
1835 /* The "write_goto_address" emit_ops method for s390 and s390x. */
1838 s390_write_goto_address (CORE_ADDR from
, CORE_ADDR to
, int size
)
1840 long diff
= ((long) (to
- (from
- 2))) / 2;
1842 unsigned char buf
[sizeof sdiff
];
1844 /* We're only doing 4-byte sizes at the moment. */
1845 if (size
!= sizeof sdiff
|| sdiff
!= diff
)
1851 memcpy (buf
, &sdiff
, sizeof sdiff
);
1852 target_write_memory (from
, buf
, sizeof sdiff
);
1855 /* Preparation for emitting a literal pool of given size. Loads the address
1856 of the pool into %r1, and jumps over it. Called should emit the pool data
1857 immediately afterwards. Used for both s390 and s390x. */
1860 s390_emit_litpool (int size
)
1862 static const unsigned char nop
[] = {
1865 unsigned char buf
[] = {
1867 (unsigned char) ((size
+ 4) / 2), /* bras %r1, .Lend+size */
1872 /* buf needs to start at even halfword for litpool to be aligned */
1873 if (current_insn_ptr
& 2)
1874 add_insns (nop
, sizeof nop
);
1878 while ((current_insn_ptr
& 6) != 4)
1879 add_insns (nop
, sizeof nop
);
1881 add_insns (buf
, sizeof buf
);
1884 /* The "emit_const" emit_ops method for s390. */
1887 s390_emit_const (LONGEST num
)
1889 unsigned long long n
= num
;
1890 unsigned char buf_s
[] = {
1891 /* lhi %r3, <num> */
1893 (unsigned char) (num
>> 8), (unsigned char) num
,
1897 static const unsigned char buf_l
[] = {
1898 0x98, 0x23, 0x10, 0x00, /* lm %r2, %r3, 0(%r1) */
1900 if (num
< 0x8000 && num
>= 0)
1902 add_insns (buf_s
, sizeof buf_s
);
1906 s390_emit_litpool (8);
1907 add_insns ((unsigned char *) &n
, sizeof n
);
1908 add_insns (buf_l
, sizeof buf_l
);
1912 /* The "emit_call" emit_ops method for s390. */
1915 s390_emit_call (CORE_ADDR fn
)
1917 unsigned int n
= fn
;
1918 static const unsigned char buf
[] = {
1919 0x58, 0x10, 0x10, 0x00, /* l %r1, 0(%r1) */
1920 0xa7, 0xfa, 0xff, 0xa0, /* ahi %r15, -0x60 */
1921 0x0d, 0xe1, /* basr %r14, %r1 */
1922 0xa7, 0xfa, 0x00, 0x60, /* ahi %r15, 0x60 */
1924 s390_emit_litpool (4);
1925 add_insns ((unsigned char *) &n
, sizeof n
);
1926 add_insns (buf
, sizeof buf
);
1929 /* The "emit_reg" emit_ops method for s390. */
1932 s390_emit_reg (int reg
)
1934 unsigned char bufpre
[] = {
1937 /* lhi %r3, <reg> */
1938 0xa7, 0x38, (unsigned char) (reg
>> 8), (unsigned char) reg
,
1940 add_insns (bufpre
, sizeof bufpre
);
1941 s390_emit_call (get_raw_reg_func_addr ());
1944 /* The "emit_pop" emit_ops method for s390. */
1947 s390_emit_pop (void)
1949 static const unsigned char buf
[] = {
1950 0x98, 0x23, 0xf0, 0x00, /* lm %r2, %r3, 0(%r15) */
1951 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
1953 add_insns (buf
, sizeof buf
);
1956 /* The "emit_stack_flush" emit_ops method for s390. */
1959 s390_emit_stack_flush (void)
1961 static const unsigned char buf
[] = {
1962 0xa7, 0xfa, 0xff, 0xf8, /* ahi %r15, -8 */
1963 0x90, 0x23, 0xf0, 0x00, /* stm %r2, %r3, 0(%r15) */
1965 add_insns (buf
, sizeof buf
);
1968 /* The "emit_zero_ext" emit_ops method for s390. */
1971 s390_emit_zero_ext (int arg
)
1973 unsigned char buf
[] = {
1974 0x8d, 0x20, 0x00, (unsigned char) (64 - arg
), /* sldl %r2, <64-arg> */
1975 0x8c, 0x20, 0x00, (unsigned char) (64 - arg
), /* srdl %r2, <64-arg> */
1977 add_insns (buf
, sizeof buf
);
1980 /* The "emit_swap" emit_ops method for s390. */
1983 s390_emit_swap (void)
1985 static const unsigned char buf
[] = {
1986 0x98, 0x45, 0xf0, 0x00, /* lm %r4, %r5, 0(%r15) */
1987 0x90, 0x23, 0xf0, 0x00, /* stm %r2, %r3, 0(%r15) */
1988 0x18, 0x24, /* lr %r2, %r4 */
1989 0x18, 0x35, /* lr %r3, %r5 */
1991 add_insns (buf
, sizeof buf
);
1994 /* The "emit_stack_adjust" emit_ops method for s390. */
1997 s390_emit_stack_adjust (int n
)
1999 unsigned char buf
[] = {
2002 (unsigned char ) (n
* 8 >> 8), (unsigned char) (n
* 8),
2004 add_insns (buf
, sizeof buf
);
2007 /* Sets %r2 to a 32-bit constant. */
2010 s390_emit_set_r2 (int arg1
)
2012 unsigned char buf_s
[] = {
2013 /* lhi %r2, <arg1> */
2014 0xa7, 0x28, (unsigned char) (arg1
>> 8), (unsigned char) arg1
,
2016 static const unsigned char buf_l
[] = {
2017 0x58, 0x20, 0x10, 0x00, /* l %r2, 0(%r1) */
2019 if (arg1
< 0x8000 && arg1
>= -0x8000)
2021 add_insns (buf_s
, sizeof buf_s
);
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. */
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. */
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. */
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
);
2083 /* The "emit_ne_goto" emit_ops method for s390. */
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
);
2103 /* The "emit_lt_goto" emit_ops method for s390. */
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 */
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 */
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> */
2124 add_insns (buf
, sizeof buf
);
2131 /* The "emit_le_goto" emit_ops method for s390. */
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 */
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 */
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> */
2152 add_insns (buf
, sizeof buf
);
2159 /* The "emit_gt_goto" emit_ops method for s390. */
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 */
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 */
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> */
2180 add_insns (buf
, sizeof buf
);
2187 /* The "emit_ge_goto" emit_ops method for s390. */
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 */
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 */
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> */
2208 add_insns (buf
, sizeof buf
);
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
=
2226 s390_emit_rsh_signed
,
2227 s390_emit_rsh_unsigned
,
2235 s390_emit_less_signed
,
2236 s390_emit_less_unsigned
,
2240 s390_write_goto_address
,
2245 s390_emit_stack_flush
,
2248 s390_emit_stack_adjust
,
2249 s390_emit_int_call_1
,
2250 s390_emit_void_call_2
,
2261 /* The "emit_prologue" emit_ops method for s390x. */
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. */
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. */
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. */
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. */
2318 s390x_emit_mul (void)
2323 /* The "emit_lsh" emit_ops method for s390x. */
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. */
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. */
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. */
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. */
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. */
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. */
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. */
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. */
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. */
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. */
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 */
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. */
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 */
2473 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
2475 add_insns (buf
, sizeof buf
);
2478 /* The "emit_ref" emit_ops method for s390x. */
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) */
2498 add_insns (buf1
, sizeof buf1
);
2501 add_insns (buf2
, sizeof buf2
);
2504 add_insns (buf4
, sizeof buf4
);
2507 add_insns (buf8
, sizeof buf8
);
2514 /* The "emit_if_goto" emit_ops method for s390x. */
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
);
2532 /* The "emit_const" emit_ops method for s390x. */
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)
2547 add_insns (buf_s
, sizeof buf_s
);
2551 s390_emit_litpool (8);
2552 add_insns ((unsigned char *) &n
, sizeof n
);
2553 add_insns (buf_l
, sizeof buf_l
);
2557 /* The "emit_call" emit_ops method for s390x. */
2560 s390x_emit_call (CORE_ADDR fn
)
2562 unsigned long n
= fn
;
2563 static const unsigned char buf
[] = {
2564 0xe3, 0x10, 0x10, 0x00, 0x00, 0x04, /* lg %r1, 0(%r1) */
2565 0xa7, 0xfb, 0xff, 0x60, /* aghi %r15, -0xa0 */
2566 0x0d, 0xe1, /* basr %r14, %r1 */
2567 0xa7, 0xfb, 0x00, 0xa0, /* aghi %r15, 0xa0 */
2569 s390_emit_litpool (8);
2570 add_insns ((unsigned char *) &n
, sizeof n
);
2571 add_insns (buf
, sizeof buf
);
2574 /* The "emit_reg" emit_ops method for s390x. */
2577 s390x_emit_reg (int reg
)
2579 unsigned char buf
[] = {
2581 0xb9, 0x04, 0x00, 0x29,
2582 /* lghi %r3, <reg> */
2583 0xa7, 0x39, (unsigned char) (reg
>> 8), (unsigned char) reg
,
2585 add_insns (buf
, sizeof buf
);
2586 s390x_emit_call (get_raw_reg_func_addr ());
2589 /* The "emit_pop" emit_ops method for s390x. */
2592 s390x_emit_pop (void)
2594 static const unsigned char buf
[] = {
2595 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x04, /* lg %r2, 0(%r15) */
2596 0x41, 0xf0, 0xf0, 0x08, /* la %r15, 8(%r15) */
2598 add_insns (buf
, sizeof buf
);
2601 /* The "emit_stack_flush" emit_ops method for s390x. */
2604 s390x_emit_stack_flush (void)
2606 static const unsigned char buf
[] = {
2607 0xa7, 0xfb, 0xff, 0xf8, /* aghi %r15, -8 */
2608 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x24, /* stg %r2, 0(%r15) */
2610 add_insns (buf
, sizeof buf
);
2613 /* The "emit_zero_ext" emit_ops method for s390x. */
2616 s390x_emit_zero_ext (int arg
)
2618 unsigned char buf
[] = {
2619 /* sllg %r2, %r2, <64-arg> */
2620 0xeb, 0x22, 0x00, (unsigned char) (64 - arg
), 0x00, 0x0d,
2621 /* srlg %r2, %r2, <64-arg> */
2622 0xeb, 0x22, 0x00, (unsigned char) (64 - arg
), 0x00, 0x0c,
2624 add_insns (buf
, sizeof buf
);
2627 /* The "emit_swap" emit_ops method for s390x. */
2630 s390x_emit_swap (void)
2632 static const unsigned char buf
[] = {
2633 0xe3, 0x30, 0xf0, 0x00, 0x00, 0x04, /* lg %r3, 0(%r15) */
2634 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x24, /* stg %r2, 0(%r15) */
2635 0xb9, 0x04, 0x00, 0x23, /* lgr %r2, %r3 */
2637 add_insns (buf
, sizeof buf
);
2640 /* The "emit_stack_adjust" emit_ops method for s390x. */
2643 s390x_emit_stack_adjust (int n
)
2645 unsigned char buf
[] = {
2646 /* aghi %r15, 8*n */
2648 (unsigned char) (n
* 8 >> 8), (unsigned char) (n
* 8),
2650 add_insns (buf
, sizeof buf
);
2653 /* The "emit_int_call_1" emit_ops method for s390x. */
2656 s390x_emit_int_call_1 (CORE_ADDR fn
, int arg1
)
2658 /* FN's prototype is `LONGEST(*fn)(int)'. */
2659 s390x_emit_const (arg1
);
2660 s390x_emit_call (fn
);
2663 /* The "emit_void_call_2" emit_ops method for s390x. */
2666 s390x_emit_void_call_2 (CORE_ADDR fn
, int arg1
)
2668 /* FN's prototype is `void(*fn)(int,LONGEST)'. */
2669 static const unsigned char buf
[] = {
2670 0xb9, 0x04, 0x00, 0x32, /* lgr %r3, %r2 */
2671 0xb9, 0x04, 0x00, 0xc2, /* lgr %r12, %r2 */
2673 static const unsigned char buf2
[] = {
2674 0xb9, 0x04, 0x00, 0x2c, /* lgr %r2, %r12 */
2676 add_insns (buf
, sizeof buf
);
2677 s390x_emit_const (arg1
);
2678 s390x_emit_call (fn
);
2679 add_insns (buf2
, sizeof buf2
);
2682 /* The "emit_eq_goto" emit_ops method for s390x. */
2685 s390x_emit_eq_goto (int *offset_p
, int *size_p
)
2687 static const unsigned char buf
[] = {
2688 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20, /* cg %r2, 0(%r15) */
2689 0xe3, 0x20, 0xf0, 0x08, 0x00, 0x04, /* lg %r2, 8(%r15) */
2690 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2691 0xc0, 0x84, 0x00, 0x00, 0x00, 0x00, /* jge <fillme> */
2693 add_insns (buf
, sizeof buf
);
2700 /* The "emit_ne_goto" emit_ops method for s390x. */
2703 s390x_emit_ne_goto (int *offset_p
, int *size_p
)
2705 static const unsigned char buf
[] = {
2706 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20, /* cg %r2, 0(%r15) */
2707 0xe3, 0x20, 0xf0, 0x08, 0x00, 0x04, /* lg %r2, 8(%r15) */
2708 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2709 0xc0, 0x74, 0x00, 0x00, 0x00, 0x00, /* jgne <fillme> */
2711 add_insns (buf
, sizeof buf
);
2718 /* The "emit_lt_goto" emit_ops method for s390x. */
2721 s390x_emit_lt_goto (int *offset_p
, int *size_p
)
2723 static const unsigned char buf
[] = {
2724 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20, /* cg %r2, 0(%r15) */
2725 0xe3, 0x20, 0xf0, 0x08, 0x00, 0x04, /* lg %r2, 8(%r15) */
2726 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2727 0xc0, 0x24, 0x00, 0x00, 0x00, 0x00, /* jgh <fillme> */
2729 add_insns (buf
, sizeof buf
);
2736 /* The "emit_le_goto" emit_ops method for s390x. */
2739 s390x_emit_le_goto (int *offset_p
, int *size_p
)
2741 static const unsigned char buf
[] = {
2742 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20, /* cg %r2, 0(%r15) */
2743 0xe3, 0x20, 0xf0, 0x08, 0x00, 0x04, /* lg %r2, 8(%r15) */
2744 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2745 0xc0, 0xa4, 0x00, 0x00, 0x00, 0x00, /* jghe <fillme> */
2747 add_insns (buf
, sizeof buf
);
2754 /* The "emit_gt_goto" emit_ops method for s390x. */
2757 s390x_emit_gt_goto (int *offset_p
, int *size_p
)
2759 static const unsigned char buf
[] = {
2760 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20, /* cg %r2, 0(%r15) */
2761 0xe3, 0x20, 0xf0, 0x08, 0x00, 0x04, /* lg %r2, 8(%r15) */
2762 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2763 0xc0, 0x44, 0x00, 0x00, 0x00, 0x00, /* jgl <fillme> */
2765 add_insns (buf
, sizeof buf
);
2772 /* The "emit_ge_goto" emit_ops method for s390x. */
2775 s390x_emit_ge_goto (int *offset_p
, int *size_p
)
2777 static const unsigned char buf
[] = {
2778 0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20, /* cg %r2, 0(%r15) */
2779 0xe3, 0x20, 0xf0, 0x08, 0x00, 0x04, /* lg %r2, 8(%r15) */
2780 0x41, 0xf0, 0xf0, 0x10, /* la %r15, 16(%r15) */
2781 0xc0, 0xc4, 0x00, 0x00, 0x00, 0x00, /* jgle <fillme> */
2783 add_insns (buf
, sizeof buf
);
2790 /* The "emit_ops" structure for s390x. */
2792 static struct emit_ops s390x_emit_ops
=
2794 s390x_emit_prologue
,
2795 s390x_emit_epilogue
,
2800 s390x_emit_rsh_signed
,
2801 s390x_emit_rsh_unsigned
,
2809 s390x_emit_less_signed
,
2810 s390x_emit_less_unsigned
,
2814 s390_write_goto_address
,
2819 s390x_emit_stack_flush
,
2820 s390x_emit_zero_ext
,
2822 s390x_emit_stack_adjust
,
2823 s390x_emit_int_call_1
,
2824 s390x_emit_void_call_2
,
2834 /* The "emit_ops" linux_target_ops method. */
2836 static struct emit_ops
*
2837 s390_emit_ops (void)
2840 struct regcache
*regcache
= get_thread_regcache (current_thread
, 0);
2842 if (register_size (regcache
->tdesc
, 0) == 8)
2843 return &s390x_emit_ops
;
2846 return &s390_emit_ops_impl
;
2849 struct linux_target_ops the_low_target
= {
2850 s390_get_thread_area
,
2851 s390_install_fast_tracepoint_jump_pad
,
2853 s390_get_min_fast_tracepoint_insn_len
,
2854 NULL
, /* supports_range_stepping */
2855 s390_supports_hardware_single_step
,
2856 NULL
, /* get_syscall_trapinfo */
2857 s390_get_ipa_tdesc_idx
,
2860 /* The linux target ops object. */
2862 linux_process_target
*the_linux_target
= &the_s390_target
;
2865 initialize_low_arch (void)
2867 /* Initialize the Linux target descriptions. */
2869 init_registers_s390_linux32 ();
2870 init_registers_s390_linux32v1 ();
2871 init_registers_s390_linux32v2 ();
2872 init_registers_s390_linux64 ();
2873 init_registers_s390_linux64v1 ();
2874 init_registers_s390_linux64v2 ();
2875 init_registers_s390_te_linux64 ();
2876 init_registers_s390_vx_linux64 ();
2877 init_registers_s390_tevx_linux64 ();
2878 init_registers_s390_gs_linux64 ();
2880 init_registers_s390x_linux64 ();
2881 init_registers_s390x_linux64v1 ();
2882 init_registers_s390x_linux64v2 ();
2883 init_registers_s390x_te_linux64 ();
2884 init_registers_s390x_vx_linux64 ();
2885 init_registers_s390x_tevx_linux64 ();
2886 init_registers_s390x_gs_linux64 ();
2889 initialize_regsets_info (&s390_regsets_info
);
2890 initialize_regsets_info (&s390_regsets_info_3264
);