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