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