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