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