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