public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: "Marcin Kościelnicki" <koriakin@0x04.net>
To: gdb-patches@sourceware.org
Cc: "Marcin Kościelnicki" <koriakin@0x04.net>
Subject: [PATCH v2] gdbserver/s390: Add support for compiled agent expressions.
Date: Fri, 04 Mar 2016 10:41:00 -0000	[thread overview]
Message-ID: <1457088067-3197-1-git-send-email-koriakin@0x04.net> (raw)
In-Reply-To: <1453637529-26972-9-git-send-email-koriakin@0x04.net>

These sequences assume a z900+ CPU, like the rest of fast tracepoint
support.

gdb/gdbserver/ChangeLog:

	* linux-s390-low.c (add_insns): New function.
	(s390_emit_prologue): New function.
	(s390_emit_epilogue): New function.
	(s390_emit_add): New function.
	(s390_emit_sub): New function.
	(s390_emit_mul): New function.
	(s390_emit_lsh): New function.
	(s390_emit_rsh_signed): New function.
	(s390_emit_rsh_unsigned): New function.
	(s390_emit_ext): New function.
	(s390_emit_log_not): New function.
	(s390_emit_bit_and): New function.
	(s390_emit_bit_or): New function.
	(s390_emit_bit_xor): New function.
	(s390_emit_bit_not): New function.
	(s390_emit_equal): New function.
	(s390_emit_less_signed): New function.
	(s390_emit_less_unsigned): New function.
	(s390_emit_ref): New function.
	(s390_emit_if_goto): New function.
	(s390_emit_goto): New function.
	(s390_write_goto_address): New function.
	(s390_emit_litpool): New function.
	(s390_emit_const): New function.
	(s390_emit_call): New function.
	(s390_emit_reg): New function.
	(s390_emit_pop): New function.
	(s390_emit_stack_flush): New function.
	(s390_emit_zero_ext): New function.
	(s390_emit_swap): New function.
	(s390_emit_stack_adjust): New function.
	(s390_emit_set_r2): New function.
	(s390_emit_int_call_1): New function.
	(s390_emit_void_call_2): New function.
	(s390_emit_eq_goto): New function.
	(s390_emit_ne_goto): New function.
	(s390_emit_lt_goto): New function.
	(s390_emit_le_goto): New function.
	(s390_emit_gt_goto): New function.
	(s390_emit_ge_goto): New function.
	(s390x_emit_prologue): New function.
	(s390x_emit_epilogue): New function.
	(s390x_emit_add): New function.
	(s390x_emit_sub): New function.
	(s390x_emit_mul): New function.
	(s390x_emit_lsh): New function.
	(s390x_emit_rsh_signed): New function.
	(s390x_emit_rsh_unsigned): New function.
	(s390x_emit_ext): New function.
	(s390x_emit_log_not): New function.
	(s390x_emit_bit_and): New function.
	(s390x_emit_bit_or): New function.
	(s390x_emit_bit_xor): New function.
	(s390x_emit_bit_not): New function.
	(s390x_emit_equal): New function.
	(s390x_emit_less_signed): New function.
	(s390x_emit_less_unsigned): New function.
	(s390x_emit_ref): New function.
	(s390x_emit_if_goto): New function.
	(s390x_emit_const): New function.
	(s390x_emit_call): New function.
	(s390x_emit_reg): New function.
	(s390x_emit_pop): New function.
	(s390x_emit_stack_flush): New function.
	(s390x_emit_zero_ext): New function.
	(s390x_emit_swap): New function.
	(s390x_emit_stack_adjust): New function.
	(s390x_emit_int_call_1): New function.
	(s390x_emit_void_call_2): New function.
	(s390x_emit_eq_goto): New function.
	(s390x_emit_ne_goto): New function.
	(s390x_emit_lt_goto): New function.
	(s390x_emit_le_goto): New function.
	(s390x_emit_gt_goto): New function.
	(s390x_emit_ge_goto): New function.
	(s390_emit_ops): New function.
	(struct linux_target_ops): Fill in emit_ops hook.
---
Updated version: deduplicated s390_emit_goto with s390x_emit_goto,
documentation comments, indent fixes.

 gdb/gdbserver/ChangeLog        |   80 +++
 gdb/gdbserver/linux-s390-low.c | 1346 +++++++++++++++++++++++++++++++++++++++-
 2 files changed, 1425 insertions(+), 1 deletion(-)

diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index 6ff94b1..df010ab 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -1,5 +1,85 @@
 2016-03-04  Marcin Kościelnicki  <koriakin@0x04.net>
 
+	* linux-s390-low.c (add_insns): New function.
+	(s390_emit_prologue): New function.
+	(s390_emit_epilogue): New function.
+	(s390_emit_add): New function.
+	(s390_emit_sub): New function.
+	(s390_emit_mul): New function.
+	(s390_emit_lsh): New function.
+	(s390_emit_rsh_signed): New function.
+	(s390_emit_rsh_unsigned): New function.
+	(s390_emit_ext): New function.
+	(s390_emit_log_not): New function.
+	(s390_emit_bit_and): New function.
+	(s390_emit_bit_or): New function.
+	(s390_emit_bit_xor): New function.
+	(s390_emit_bit_not): New function.
+	(s390_emit_equal): New function.
+	(s390_emit_less_signed): New function.
+	(s390_emit_less_unsigned): New function.
+	(s390_emit_ref): New function.
+	(s390_emit_if_goto): New function.
+	(s390_emit_goto): New function.
+	(s390_write_goto_address): New function.
+	(s390_emit_litpool): New function.
+	(s390_emit_const): New function.
+	(s390_emit_call): New function.
+	(s390_emit_reg): New function.
+	(s390_emit_pop): New function.
+	(s390_emit_stack_flush): New function.
+	(s390_emit_zero_ext): New function.
+	(s390_emit_swap): New function.
+	(s390_emit_stack_adjust): New function.
+	(s390_emit_set_r2): New function.
+	(s390_emit_int_call_1): New function.
+	(s390_emit_void_call_2): New function.
+	(s390_emit_eq_goto): New function.
+	(s390_emit_ne_goto): New function.
+	(s390_emit_lt_goto): New function.
+	(s390_emit_le_goto): New function.
+	(s390_emit_gt_goto): New function.
+	(s390_emit_ge_goto): New function.
+	(s390x_emit_prologue): New function.
+	(s390x_emit_epilogue): New function.
+	(s390x_emit_add): New function.
+	(s390x_emit_sub): New function.
+	(s390x_emit_mul): New function.
+	(s390x_emit_lsh): New function.
+	(s390x_emit_rsh_signed): New function.
+	(s390x_emit_rsh_unsigned): New function.
+	(s390x_emit_ext): New function.
+	(s390x_emit_log_not): New function.
+	(s390x_emit_bit_and): New function.
+	(s390x_emit_bit_or): New function.
+	(s390x_emit_bit_xor): New function.
+	(s390x_emit_bit_not): New function.
+	(s390x_emit_equal): New function.
+	(s390x_emit_less_signed): New function.
+	(s390x_emit_less_unsigned): New function.
+	(s390x_emit_ref): New function.
+	(s390x_emit_if_goto): New function.
+	(s390x_emit_const): New function.
+	(s390x_emit_call): New function.
+	(s390x_emit_reg): New function.
+	(s390x_emit_pop): New function.
+	(s390x_emit_stack_flush): New function.
+	(s390x_emit_zero_ext): New function.
+	(s390x_emit_swap): New function.
+	(s390x_emit_stack_adjust): New function.
+	(s390x_emit_int_call_1): New function.
+	(s390x_emit_void_call_2): New function.
+	(s390x_emit_eq_goto): New function.
+	(s390x_emit_ne_goto): New function.
+	(s390x_emit_lt_goto): New function.
+	(s390x_emit_le_goto): New function.
+	(s390x_emit_gt_goto): New function.
+	(s390x_emit_ge_goto): New function.
+	(s390_emit_ops): New function.
+	(struct linux_target_ops): Fill in emit_ops hook.
+
+2016-01-24  Marcin Kościelnicki  <koriakin@0x04.net>
+
 	* Makefile.in: Add s390 IPA files.
 	* configure.srv: Build IPA for s390.
 	* linux-s390-ipa.c: New file.
diff --git a/gdb/gdbserver/linux-s390-low.c b/gdb/gdbserver/linux-s390-low.c
index 146e4c9..f0d76f0 100644
--- a/gdb/gdbserver/linux-s390-low.c
+++ b/gdb/gdbserver/linux-s390-low.c
@@ -22,6 +22,8 @@
 #include "server.h"
 #include "linux-low.h"
 #include "elf/common.h"
+#include "ax.h"
+#include "tracepoint.h"
 
 #include <asm/ptrace.h>
 #include "nat/gdb_ptrace.h"
@@ -1397,6 +1399,1348 @@ s390_get_ipa_tdesc_idx (void)
   return 0;
 }
 
+/* Appends given buffer to current_insn_ptr in the target.  */
+
+static void
+add_insns (const unsigned char *start, int len)
+{
+  CORE_ADDR buildaddr = current_insn_ptr;
+
+  if (debug_threads)
+    debug_printf ("Adding %d bytes of insn at %s\n",
+		  len, paddress (buildaddr));
+
+  append_insns (&buildaddr, len, start);
+  current_insn_ptr = buildaddr;
+}
+
+/* Register usage in emit:
+
+   - %r0, %r1: temp
+   - %r2: top of stack (high word for 31-bit)
+   - %r3: low word of top of stack (for 31-bit)
+   - %r4, %r5: temp
+   - %r6, %r7, %r8: don't use
+   - %r9: saved arg1
+   - %r10: saved arg2
+   - %r11: frame pointer
+   - %r12: saved top of stack for void_call_2 (high word for 31-bit)
+   - %r13: low word of saved top of stack (for 31-bit)
+   - %r14: return address for calls
+   - %r15: stack pointer
+
+  */
+
+/* The "emit_prologue" emit_ops method for s390.  */
+
+static void
+s390_emit_prologue (void)
+{
+  static const unsigned char buf[] = {
+    0x90, 0x9f, 0xf0, 0x24,		/* stm %r9, %r15, 0x24(%r15) */
+    0x18, 0x92,				/* lr %r9, %r2 */
+    0x18, 0xa3,				/* lr %r10, %r3 */
+    0x18, 0xbf,				/* lr %r11, %r15 */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_epilogue" emit_ops method for s390.  */
+
+static void
+s390_emit_epilogue (void)
+{
+  static const unsigned char buf[] = {
+    0x90, 0x23, 0xa0, 0x00,		/* stm %r2, %r3, 0(%r10) */
+    0xa7, 0x28, 0x00, 0x00,		/* lhi %r2, 0 */
+    0x98, 0x9f, 0xb0, 0x24,		/* lm %r9, %r15, 0x24(%r11) */
+    0x07, 0xfe,				/* br %r14 */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_add" emit_ops method for s390.  */
+
+static void
+s390_emit_add (void)
+{
+  static const unsigned char buf[] = {
+    0x5e, 0x30, 0xf0, 0x04,		/* al %r3, 4(%r15) */
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x98,	/* al %r2, 0(%r15) */
+    0x41, 0xf0, 0xf0, 0x08,		/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_sub" emit_ops method for s390.  */
+
+static void
+s390_emit_sub (void)
+{
+  static const unsigned char buf[] = {
+    0x98, 0x45, 0xf0, 0x00,	/* lm %r4, %r5, 0(%r15) */
+    0x1f, 0x53,			/* slr %r5, %r3 */
+    0xb9, 0x99, 0x00, 0x42,	/* slbr %r4, %r2 */
+    0x41, 0xf0, 0xf0, 0x08,	/* la %r15, 8(%r15) */
+    0x18, 0x35,			/* lr %r3, %r5 */
+    0x18, 0x24,			/* lr %r2, %r4 */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_mul" emit_ops method for s390.  */
+
+static void
+s390_emit_mul (void)
+{
+  emit_error = 1;
+}
+
+/* The "emit_lsh" emit_ops method for s390.  */
+
+static void
+s390_emit_lsh (void)
+{
+  static const unsigned char buf[] = {
+    0x18, 0x43,			/* lr %r4, %r3 */
+    0x98, 0x23, 0xf0, 0x00,	/* lm %r2, %r3, 0(%r15) */
+    0x8d, 0x20, 0x40, 0x00,	/* sldl %r2, 0(%r4) */
+    0x41, 0xf0, 0xf0, 0x08,	/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_rsh_signed" emit_ops method for s390.  */
+
+static void
+s390_emit_rsh_signed (void)
+{
+  static const unsigned char buf[] = {
+    0x18, 0x43,			/* lr %r4, %r3 */
+    0x98, 0x23, 0xf0, 0x00,	/* lm %r2, %r3, 0(%r15) */
+    0x8e, 0x20, 0x40, 0x00,	/* srda %r2, 0(%r4) */
+    0x41, 0xf0, 0xf0, 0x08,	/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_rsh_unsigned" emit_ops method for s390.  */
+
+static void
+s390_emit_rsh_unsigned (void)
+{
+  static const unsigned char buf[] = {
+    0x18, 0x43,			/* lr %r4, %r3 */
+    0x98, 0x23, 0xf0, 0x00,	/* lm %r2, %r3, 0(%r15) */
+    0x8c, 0x20, 0x40, 0x00,	/* srdl %r2, 0(%r4) */
+    0x41, 0xf0, 0xf0, 0x08,	/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_ext" emit_ops method for s390.  */
+
+static void
+s390_emit_ext (int arg)
+{
+  unsigned char buf[] = {
+    0x8d, 0x20, 0x00, 64-arg,	/* sldl %r2, <64-arg> */
+    0x8e, 0x20, 0x00, 64-arg,	/* srda %r2, <64-arg> */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_log_not" emit_ops method for s390.  */
+
+static void
+s390_emit_log_not (void)
+{
+  static const unsigned char buf[] = {
+    0x16, 0x23,			/* or %r2, %r3 */
+    0xa7, 0x28, 0x00, 0x00,	/* lhi %r2, 0 */
+    0xa7, 0x38, 0x00, 0x00,	/* lhi %r3, 0 */
+    0xa7, 0x74, 0x00, 0x04,	/* jne .Lskip */
+    0xa7, 0x38, 0x00, 0x01,	/* lhi %r3, 1 */
+    /* .Lskip: */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_bit_and" emit_ops method for s390.  */
+
+static void
+s390_emit_bit_and (void)
+{
+  static const unsigned char buf[] = {
+    0x54, 0x20, 0xf0, 0x00,	/* n %r2, 0(%r15) */
+    0x54, 0x30, 0xf0, 0x04,	/* n %r3, 4(%r15) */
+    0x41, 0xf0, 0xf0, 0x08,	/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_bit_or" emit_ops method for s390.  */
+
+static void
+s390_emit_bit_or (void)
+{
+  static const unsigned char buf[] = {
+    0x56, 0x20, 0xf0, 0x00,	/* o %r2, 0(%r15) */
+    0x56, 0x30, 0xf0, 0x04,	/* o %r3, 4(%r15) */
+    0x41, 0xf0, 0xf0, 0x08,	/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_bit_xor" emit_ops method for s390.  */
+
+static void
+s390_emit_bit_xor (void)
+{
+  static const unsigned char buf[] = {
+    0x57, 0x20, 0xf0, 0x00,	/* x %r2, 0(%r15) */
+    0x57, 0x30, 0xf0, 0x04,	/* x %r3, 4(%r15) */
+    0x41, 0xf0, 0xf0, 0x08,	/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_bit_not" emit_ops method for s390.  */
+
+static void
+s390_emit_bit_not (void)
+{
+  static const unsigned char buf[] = {
+    0xa7, 0x48, 0xff, 0xff,	/* lhi %r4, -1 */
+    0x17, 0x24,			/* xr %r2, %r4 */
+    0x17, 0x34,			/* xr %r3, %r4 */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_equal" emit_ops method for s390.  */
+
+static void
+s390_emit_equal (void)
+{
+  s390_emit_bit_xor ();
+  s390_emit_log_not ();
+}
+
+/* The "emit_less_signed" emit_ops method for s390.  */
+
+static void
+s390_emit_less_signed (void)
+{
+  static const unsigned char buf[] = {
+    0x59, 0x20, 0xf0, 0x00,	/* c %r2, 0(%r15) */
+    0xa7, 0x24, 0x00, 0x0c,	/* jh .Lless */
+    0xa7, 0x44, 0x00, 0x06,	/* jl .Lhigh */
+    0x55, 0x30, 0xf0, 0x04,	/* cl %r3, 4(%r15) */
+    0xa7, 0x24, 0x00, 0x06,	/* jh .Lless */
+    /* .Lhigh: */
+    0xa7, 0x38, 0x00, 0x00,	/* lhi %r3, 0 */
+    0xa7, 0xf4, 0x00, 0x04,	/* j .Lend */
+    /* .Lless: */
+    0xa7, 0x38, 0x00, 0x01,	/* lhi %r3, 1 */
+    /* .Lend: */
+    0xa7, 0x28, 0x00, 0x00,	/* lhi %r2, 0 */
+    0x41, 0xf0, 0xf0, 0x08,	/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_less_unsigned" emit_ops method for s390.  */
+
+static void
+s390_emit_less_unsigned (void)
+{
+  static const unsigned char buf[] = {
+    0x55, 0x20, 0xf0, 0x00,	/* cl %r2, 0(%r15) */
+    0xa7, 0x24, 0x00, 0x0c,	/* jh .Lless */
+    0xa7, 0x44, 0x00, 0x06,	/* jl .Lhigh */
+    0x55, 0x30, 0xf0, 0x04,	/* cl %r3, 4(%r15) */
+    0xa7, 0x24, 0x00, 0x06,	/* jh .Lless */
+    /* .Lhigh: */
+    0xa7, 0x38, 0x00, 0x00,	/* lhi %r3, 0 */
+    0xa7, 0xf4, 0x00, 0x04,	/* j .Lend */
+    /* .Lless: */
+    0xa7, 0x38, 0x00, 0x01,	/* lhi %r3, 1 */
+    /* .Lend: */
+    0xa7, 0x28, 0x00, 0x00,	/* lhi %r2, 0 */
+    0x41, 0xf0, 0xf0, 0x08,	/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_ref" emit_ops method for s390.  */
+
+static void
+s390_emit_ref (int size)
+{
+  static const unsigned char buf1[] = {
+    0xa7, 0x28, 0x00, 0x00,	/* lhi %r2, 0 */
+    0x43, 0x30, 0x30, 0x00,	/* ic %r3, 0(%r3) */
+  };
+  static const unsigned char buf2[] = {
+    0xa7, 0x28, 0x00, 0x00,	/* lhi %r2, 0 */
+    0x48, 0x30, 0x30, 0x00,	/* lh %r3, 0(%r3) */
+  };
+  static const unsigned char buf4[] = {
+    0xa7, 0x28, 0x00, 0x00,	/* lhi %r2, 0 */
+    0x58, 0x30, 0x30, 0x00,	/* l %r3, 0(%r3) */
+  };
+  static const unsigned char buf8[] = {
+    0x98, 0x23, 0x30, 0x00,	/* lm %r2, %r3, 0(%r3) */
+  };
+  switch (size)
+    {
+    case 1:
+      add_insns (buf1, sizeof buf1);
+      break;
+    case 2:
+      add_insns (buf2, sizeof buf2);
+      break;
+    case 4:
+      add_insns (buf4, sizeof buf4);
+      break;
+    case 8:
+      add_insns (buf8, sizeof buf8);
+      break;
+    default:
+      emit_error = 1;
+    }
+}
+
+/* The "emit_if_goto" emit_ops method for s390.  */
+
+static void
+s390_emit_if_goto (int *offset_p, int *size_p)
+{
+  static const unsigned char buf[] = {
+    0x16, 0x23,				/* or %r2, %r3 */
+    0x98, 0x23, 0xf0, 0x00,		/* lm %r2, %r3, 0(%r15) */
+    0x41, 0xf0, 0xf0, 0x08,		/* la %r15, 8(%r15) */
+    0xc0, 0x74, 0x00, 0x00, 0x00, 0x00	/* jgne <fillme> */
+  };
+  add_insns (buf, sizeof buf);
+  if (offset_p)
+    *offset_p = 12;
+  if (size_p)
+    *size_p = 4;
+}
+
+/* The "emit_goto" emit_ops method for s390 and s390x.  */
+
+static void
+s390_emit_goto (int *offset_p, int *size_p)
+{
+  static const unsigned char buf[] = {
+    0xc0, 0xf4, 0x00, 0x00, 0x00, 0x00,	/* jg <fillme> */
+  };
+  add_insns (buf, sizeof buf);
+  if (offset_p)
+    *offset_p = 2;
+  if (size_p)
+    *size_p = 4;
+}
+
+/* The "write_goto_address" emit_ops method for s390 and s390x.  */
+
+static void
+s390_write_goto_address (CORE_ADDR from, CORE_ADDR to, int size)
+{
+  long diff = ((long) (to - (from - 2))) / 2;
+  int sdiff = diff;
+  unsigned char buf[sizeof sdiff];
+
+  /* We're only doing 4-byte sizes at the moment.  */
+  if (size != sizeof sdiff || sdiff != diff)
+    {
+      emit_error = 1;
+      return;
+    }
+
+  memcpy (buf, &sdiff, sizeof sdiff);
+  write_inferior_memory (from, buf, sizeof sdiff);
+}
+
+/* Preparation for emitting a literal pool of given size.  Loads the address
+   of the pool into %r1, and jumps over it.  Called should emit the pool data
+   immediately afterwards.  Used for both s390 and s390x.  */
+
+static void
+s390_emit_litpool (int size)
+{
+  static const unsigned char nop[] = {
+    0x07, 0x07,
+  };
+  unsigned char buf[] = {
+    0xa7, 0x15, 0x00, (size + 4) / 2,	/* bras %r1, .Lend+size */
+    /* .Lend: */
+  };
+  if (size == 4)
+    {
+      /* buf needs to start at even halfword for litpool to be aligned */
+      if (current_insn_ptr & 2)
+	add_insns (nop, sizeof nop);
+    }
+  else
+    {
+      while ((current_insn_ptr & 6) != 4)
+	add_insns (nop, sizeof nop);
+    }
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_const" emit_ops method for s390.  */
+
+static void
+s390_emit_const (LONGEST num)
+{
+  unsigned long long n = num;
+  unsigned char buf_s[] = {
+    0xa7, 0x38, num >> 8, num,	/* lhi %r3, <num> */
+    0x17, 0x22,			/* xr %r2, %r2 */
+  };
+  static const unsigned char buf_l[] = {
+    0x98, 0x23, 0x10, 0x00,	/* lm %r2, %r3, 0(%r1) */
+  };
+  if (num < 0x8000 && num >= 0)
+  {
+    add_insns (buf_s, sizeof buf_s);
+  }
+  else
+  {
+    s390_emit_litpool (8);
+    add_insns ((unsigned char *) &n, sizeof n);
+    add_insns (buf_l, sizeof buf_l);
+  }
+}
+
+/* The "emit_call" emit_ops method for s390.  */
+
+static void
+s390_emit_call (CORE_ADDR fn)
+{
+  unsigned int n = fn;
+  static const unsigned char buf[] = {
+    0x58, 0x10, 0x10, 0x00,	/* l %r1, 0(%r1) */
+    0xa7, 0xfa, 0xff, 0xa0,	/* ahi %r15, -0x60 */
+    0x0d, 0xe1,			/* basr %r14, %r1 */
+    0xa7, 0xfa, 0x00, 0x60,	/* ahi %r15, 0x60 */
+  };
+  s390_emit_litpool (4);
+  add_insns ((unsigned char *) &n, sizeof n);
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_reg" emit_ops method for s390.  */
+
+static void
+s390_emit_reg (int reg)
+{
+  unsigned char bufpre[] = {
+    0x18, 0x29,			/* lr %r2, %r9 */
+    0xa7, 0x38, reg >> 8, reg,	/* lhi %r3, <reg> */
+  };
+  add_insns (bufpre, sizeof bufpre);
+  s390_emit_call (get_raw_reg_func_addr ());
+}
+
+/* The "emit_pop" emit_ops method for s390.  */
+
+static void
+s390_emit_pop (void)
+{
+  static const unsigned char buf[] = {
+    0x98, 0x23, 0xf0, 0x00,	/* lm %r2, %r3, 0(%r15) */
+    0x41, 0xf0, 0xf0, 0x08,	/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_stack_flush" emit_ops method for s390.  */
+
+static void
+s390_emit_stack_flush (void)
+{
+  static const unsigned char buf[] = {
+    0xa7, 0xfa, 0xff, 0xf8,	/* ahi %r15, -8 */
+    0x90, 0x23, 0xf0, 0x00,	/* stm %r2, %r3, 0(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_zero_ext" emit_ops method for s390.  */
+
+static void
+s390_emit_zero_ext (int arg)
+{
+  unsigned char buf[] = {
+    0x8d, 0x20, 0x00, 64-arg,	/* sldl %r2, <64-arg> */
+    0x8c, 0x20, 0x00, 64-arg,	/* srdl %r2, <64-arg> */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_swap" emit_ops method for s390.  */
+
+static void
+s390_emit_swap (void)
+{
+  static const unsigned char buf[] = {
+    0x98, 0x45, 0xf0, 0x00,	/* lm %r4, %r5, 0(%r15) */
+    0x90, 0x23, 0xf0, 0x00,	/* stm %r2, %r3, 0(%r15) */
+    0x18, 0x24,			/* lr %r2, %r4 */
+    0x18, 0x35,			/* lr %r3, %r5 */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_stack_adjust" emit_ops method for s390.  */
+
+static void
+s390_emit_stack_adjust (int n)
+{
+  unsigned char buf[] = {
+    0xa7, 0xfa, n * 8 >> 8, n * 8,	/* ahi %r15, 8*n */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* Sets %r2 to a 32-bit constant.  */
+
+static void
+s390_emit_set_r2 (int arg1)
+{
+  unsigned char buf_s[] = {
+    0xa7, 0x28, arg1 >> 8, arg1,	/* lhi %r2, <arg1> */
+  };
+  static const unsigned char buf_l[] = {
+    0x58, 0x20, 0x10, 0x00,	/* l %r2, 0(%r1) */
+  };
+  if (arg1 < 0x8000 && arg1 >= -0x8000)
+  {
+    add_insns (buf_s, sizeof buf_s);
+  }
+  else
+  {
+    s390_emit_litpool (4);
+    add_insns ((unsigned char *) &arg1, sizeof arg1);
+    add_insns (buf_l, sizeof buf_l);
+  }
+}
+
+/* The "emit_int_call_1" emit_ops method for s390.  */
+
+static void
+s390_emit_int_call_1 (CORE_ADDR fn, int arg1)
+{
+  /* FN's prototype is `LONGEST(*fn)(int)'.  */
+  s390_emit_set_r2 (arg1);
+  s390_emit_call (fn);
+}
+
+/* The "emit_void_call_2" emit_ops method for s390.  */
+
+static void
+s390_emit_void_call_2 (CORE_ADDR fn, int arg1)
+{
+  /* FN's prototype is `void(*fn)(int,LONGEST)'.  */
+  static const unsigned char buf[] = {
+    0x18, 0xc2,			/* lr %r12, %r2 */
+    0x18, 0xd3,			/* lr %r13, %r3 */
+    0x18, 0x43,			/* lr %r4, %r3 */
+    0x18, 0x32,			/* lr %r3, %r2 */
+  };
+  static const unsigned char buf2[] = {
+    0x18, 0x2c,			/* lr %r2, %r12 */
+    0x18, 0x3d,			/* lr %r3, %r13 */
+  };
+  add_insns (buf, sizeof buf);
+  s390_emit_set_r2 (arg1);
+  s390_emit_call (fn);
+  add_insns (buf2, sizeof buf2);
+}
+
+/* The "emit_eq_goto" emit_ops method for s390.  */
+
+void
+s390_emit_eq_goto (int *offset_p, int *size_p)
+{
+  static const unsigned char buf[] = {
+    0x57, 0x20, 0xf0, 0x00,		/* x %r2, 0(%r15) */
+    0x57, 0x30, 0xf0, 0x04,		/* x %r3, 4(%r15) */
+    0x16, 0x23,				/* or %r2, %r3 */
+    0x98, 0x23, 0xf0, 0x08,		/* lm %r2, %r3, 8(%r15) */
+    0x41, 0xf0, 0xf0, 0x10,		/* la %r15, 16(%r15) */
+    0xc0, 0x84, 0x00, 0x00, 0x00, 0x00,	/* jge <fillme> */
+  };
+  add_insns (buf, sizeof buf);
+  if (offset_p)
+    *offset_p = 20;
+  if (size_p)
+    *size_p = 4;
+}
+
+/* The "emit_ne_goto" emit_ops method for s390.  */
+
+void
+s390_emit_ne_goto (int *offset_p, int *size_p)
+{
+  static const unsigned char buf[] = {
+    0x57, 0x20, 0xf0, 0x00,		/* x %r2, 0(%r15) */
+    0x57, 0x30, 0xf0, 0x04,		/* x %r3, 4(%r15) */
+    0x16, 0x23,				/* or %r2, %r3 */
+    0x98, 0x23, 0xf0, 0x08,		/* lm %r2, %r3, 8(%r15) */
+    0x41, 0xf0, 0xf0, 0x10,		/* la %r15, 16(%r15) */
+    0xc0, 0x74, 0x00, 0x00, 0x00, 0x00,	/* jgne <fillme> */
+  };
+  add_insns (buf, sizeof buf);
+  if (offset_p)
+    *offset_p = 20;
+  if (size_p)
+    *size_p = 4;
+}
+
+/* The "emit_lt_goto" emit_ops method for s390.  */
+
+void
+s390_emit_lt_goto (int *offset_p, int *size_p)
+{
+  static const unsigned char buf[] = {
+    0x59, 0x20, 0xf0, 0x00,		/* c %r2, 0(%r15) */
+    0xa7, 0x24, 0x00, 0x0e,		/* jh .Ltrue */
+    0xa7, 0x44, 0x00, 0x06,		/* jl .Lfalse */
+    0x55, 0x30, 0xf0, 0x04,		/* cl %r3, 4(%r15) */
+    0xa7, 0x24, 0x00, 0x08,		/* jh .Ltrue */
+    /* .Lfalse: */
+    0x98, 0x23, 0xf0, 0x08,		/* lm %r2, %r3, 8(%r15) */
+    0x41, 0xf0, 0xf0, 0x10,		/* la %r15, 16(%r15) */
+    0xa7, 0xf4, 0x00, 0x09,		/* j .Lend */
+    /* .Ltrue: */
+    0x98, 0x23, 0xf0, 0x08,		/* lm %r2, %r3, 8(%r15) */
+    0x41, 0xf0, 0xf0, 0x10,		/* la %r15, 16(%r15) */
+    0xc0, 0xf4, 0x00, 0x00, 0x00, 0x00,	/* jg <fillme> */
+    /* .Lend: */
+  };
+  add_insns (buf, sizeof buf);
+  if (offset_p)
+    *offset_p = 42;
+  if (size_p)
+    *size_p = 4;
+}
+
+/* The "emit_le_goto" emit_ops method for s390.  */
+
+void
+s390_emit_le_goto (int *offset_p, int *size_p)
+{
+  static const unsigned char buf[] = {
+    0x59, 0x20, 0xf0, 0x00,		/* c %r2, 0(%r15) */
+    0xa7, 0x24, 0x00, 0x0e,		/* jh .Ltrue */
+    0xa7, 0x44, 0x00, 0x06,		/* jl .Lfalse */
+    0x55, 0x30, 0xf0, 0x04,		/* cl %r3, 4(%r15) */
+    0xa7, 0xa4, 0x00, 0x08,		/* jhe .Ltrue */
+    /* .Lfalse: */
+    0x98, 0x23, 0xf0, 0x08,		/* lm %r2, %r3, 8(%r15) */
+    0x41, 0xf0, 0xf0, 0x10,		/* la %r15, 16(%r15) */
+    0xa7, 0xf4, 0x00, 0x09,		/* j .Lend */
+    /* .Ltrue: */
+    0x98, 0x23, 0xf0, 0x08,		/* lm %r2, %r3, 8(%r15) */
+    0x41, 0xf0, 0xf0, 0x10,		/* la %r15, 16(%r15) */
+    0xc0, 0xf4, 0x00, 0x00, 0x00, 0x00,	/* jg <fillme> */
+    /* .Lend: */
+  };
+  add_insns (buf, sizeof buf);
+  if (offset_p)
+    *offset_p = 42;
+  if (size_p)
+    *size_p = 4;
+}
+
+/* The "emit_gt_goto" emit_ops method for s390.  */
+
+void
+s390_emit_gt_goto (int *offset_p, int *size_p)
+{
+  static const unsigned char buf[] = {
+    0x59, 0x20, 0xf0, 0x00,		/* c %r2, 0(%r15) */
+    0xa7, 0x44, 0x00, 0x0e,		/* jl .Ltrue */
+    0xa7, 0x24, 0x00, 0x06,		/* jh .Lfalse */
+    0x55, 0x30, 0xf0, 0x04,		/* cl %r3, 4(%r15) */
+    0xa7, 0x44, 0x00, 0x08,		/* jl .Ltrue */
+    /* .Lfalse: */
+    0x98, 0x23, 0xf0, 0x08,		/* lm %r2, %r3, 8(%r15) */
+    0x41, 0xf0, 0xf0, 0x10,		/* la %r15, 16(%r15) */
+    0xa7, 0xf4, 0x00, 0x09,		/* j .Lend */
+    /* .Ltrue: */
+    0x98, 0x23, 0xf0, 0x08,		/* lm %r2, %r3, 8(%r15) */
+    0x41, 0xf0, 0xf0, 0x10,		/* la %r15, 16(%r15) */
+    0xc0, 0xf4, 0x00, 0x00, 0x00, 0x00,	/* jg <fillme> */
+    /* .Lend: */
+  };
+  add_insns (buf, sizeof buf);
+  if (offset_p)
+    *offset_p = 42;
+  if (size_p)
+    *size_p = 4;
+}
+
+/* The "emit_ge_goto" emit_ops method for s390.  */
+
+void
+s390_emit_ge_goto (int *offset_p, int *size_p)
+{
+  static const unsigned char buf[] = {
+    0x59, 0x20, 0xf0, 0x00,		/* c %r2, 0(%r15) */
+    0xa7, 0x44, 0x00, 0x0e,		/* jl .Ltrue */
+    0xa7, 0x24, 0x00, 0x06,		/* jh .Lfalse */
+    0x55, 0x30, 0xf0, 0x04,		/* cl %r3, 4(%r15) */
+    0xa7, 0xc4, 0x00, 0x08,		/* jle .Ltrue */
+    /* .Lfalse: */
+    0x98, 0x23, 0xf0, 0x08,		/* lm %r2, %r3, 8(%r15) */
+    0x41, 0xf0, 0xf0, 0x10,		/* la %r15, 16(%r15) */
+    0xa7, 0xf4, 0x00, 0x09,		/* j .Lend */
+    /* .Ltrue: */
+    0x98, 0x23, 0xf0, 0x08,		/* lm %r2, %r3, 8(%r15) */
+    0x41, 0xf0, 0xf0, 0x10,		/* la %r15, 16(%r15) */
+    0xc0, 0xf4, 0x00, 0x00, 0x00, 0x00,	/* jg <fillme> */
+    /* .Lend: */
+  };
+  add_insns (buf, sizeof buf);
+  if (offset_p)
+    *offset_p = 42;
+  if (size_p)
+    *size_p = 4;
+}
+
+/* The "emit_ops" structure for s390.  Named _impl to avoid name
+   collision with s390_emit_ops function.  */
+
+struct emit_ops s390_emit_ops_impl =
+  {
+    s390_emit_prologue,
+    s390_emit_epilogue,
+    s390_emit_add,
+    s390_emit_sub,
+    s390_emit_mul,
+    s390_emit_lsh,
+    s390_emit_rsh_signed,
+    s390_emit_rsh_unsigned,
+    s390_emit_ext,
+    s390_emit_log_not,
+    s390_emit_bit_and,
+    s390_emit_bit_or,
+    s390_emit_bit_xor,
+    s390_emit_bit_not,
+    s390_emit_equal,
+    s390_emit_less_signed,
+    s390_emit_less_unsigned,
+    s390_emit_ref,
+    s390_emit_if_goto,
+    s390_emit_goto,
+    s390_write_goto_address,
+    s390_emit_const,
+    s390_emit_call,
+    s390_emit_reg,
+    s390_emit_pop,
+    s390_emit_stack_flush,
+    s390_emit_zero_ext,
+    s390_emit_swap,
+    s390_emit_stack_adjust,
+    s390_emit_int_call_1,
+    s390_emit_void_call_2,
+    s390_emit_eq_goto,
+    s390_emit_ne_goto,
+    s390_emit_lt_goto,
+    s390_emit_le_goto,
+    s390_emit_gt_goto,
+    s390_emit_ge_goto
+  };
+
+#ifdef __s390x__
+
+/* The "emit_prologue" emit_ops method for s390x.  */
+
+static void
+s390x_emit_prologue (void)
+{
+  static const unsigned char buf[] = {
+    0xeb, 0x9f, 0xf0, 0x48, 0x00, 0x24,	/* stmg %r9, %r15, 0x48(%r15) */
+    0xb9, 0x04, 0x00, 0x92,		/* lgr %r9, %r2 */
+    0xb9, 0x04, 0x00, 0xa3,		/* lgr %r10, %r3 */
+    0xb9, 0x04, 0x00, 0xbf,		/* lgr %r11, %r15 */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_epilogue" emit_ops method for s390x.  */
+
+static void
+s390x_emit_epilogue (void)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x20, 0xa0, 0x00, 0x00, 0x24,	/* stg %r2, 0(%r10) */
+    0xa7, 0x29, 0x00, 0x00,		/* lghi %r2, 0 */
+    0xeb, 0x9f, 0xf0, 0x48, 0x00, 0x04,	/* lmg %r9, %r15, 0x48(%r15) */
+    0x07, 0xfe,				/* br %r14 */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_add" emit_ops method for s390x.  */
+
+static void
+s390x_emit_add (void)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x0a,	/* alg %r2, 0(%r15) */
+    0x41, 0xf0, 0xf0, 0x08,		/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_sub" emit_ops method for s390x.  */
+
+static void
+s390x_emit_sub (void)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x30, 0xf0, 0x00, 0x00, 0x04,	/* lg %r3, 0(%r15) */
+    0xb9, 0x0b, 0x00, 0x32,		/* slgr %r3, %r2 */
+    0xb9, 0x04, 0x00, 0x23,		/* lgr %r2, %r3 */
+    0x41, 0xf0, 0xf0, 0x08,		/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_mul" emit_ops method for s390x.  */
+
+static void
+s390x_emit_mul (void)
+{
+  emit_error = 1;
+}
+
+/* The "emit_lsh" emit_ops method for s390x.  */
+
+static void
+s390x_emit_lsh (void)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x30, 0xf0, 0x00, 0x00, 0x04,	/* lg %r3, 0(%r15) */
+    0xeb, 0x23, 0x20, 0x00, 0x00, 0x0d,	/* sllg %r2, %r3, 0(%r2) */
+    0x41, 0xf0, 0xf0, 0x08,		/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_rsh_signed" emit_ops method for s390x.  */
+
+static void
+s390x_emit_rsh_signed (void)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x30, 0xf0, 0x00, 0x00, 0x04,	/* lg %r3, 0(%r15) */
+    0xeb, 0x23, 0x20, 0x00, 0x00, 0x0a,	/* srag %r2, %r3, 0(%r2) */
+    0x41, 0xf0, 0xf0, 0x08,		/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_rsh_unsigned" emit_ops method for s390x.  */
+
+static void
+s390x_emit_rsh_unsigned (void)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x30, 0xf0, 0x00, 0x00, 0x04,	/* lg %r3, 0(%r15) */
+    0xeb, 0x23, 0x20, 0x00, 0x00, 0x0c,	/* srlg %r2, %r3, 0(%r2) */
+    0x41, 0xf0, 0xf0, 0x08,		/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_ext" emit_ops method for s390x.  */
+
+static void
+s390x_emit_ext (int arg)
+{
+  unsigned char buf[] = {
+    0xeb, 0x22, 0x00, 64-arg, 0x00, 0x0d,	/* sllg %r2, %r2, <64-arg> */
+    0xeb, 0x22, 0x00, 64-arg, 0x00, 0x0a,	/* srag %r2, %r2, <64-arg> */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_log_not" emit_ops method for s390x.  */
+
+static void
+s390x_emit_log_not (void)
+{
+  static const unsigned char buf[] = {
+    0xb9, 0x00, 0x00, 0x22,		/* lpgr %r2, %r2 */
+    0xa7, 0x2b, 0xff, 0xff,		/* aghi %r2, -1 */
+    0xeb, 0x22, 0x00, 0x3f, 0x00, 0x0c,	/* srlg %r2, %r2, 63 */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_bit_and" emit_ops method for s390x.  */
+
+static void
+s390x_emit_bit_and (void)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x80,	/* ng %r2, 0(%r15) */
+    0x41, 0xf0, 0xf0, 0x08,		/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_bit_or" emit_ops method for s390x.  */
+
+static void
+s390x_emit_bit_or (void)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x81,	/* og %r2, 0(%r15) */
+    0x41, 0xf0, 0xf0, 0x08,		/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_bit_xor" emit_ops method for s390x.  */
+
+static void
+s390x_emit_bit_xor (void)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x82,	/* xg %r2, 0(%r15) */
+    0x41, 0xf0, 0xf0, 0x08,		/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_bit_not" emit_ops method for s390x.  */
+
+static void
+s390x_emit_bit_not (void)
+{
+  static const unsigned char buf[] = {
+    0xa7, 0x39, 0xff, 0xff,	/* lghi %r3, -1 */
+    0xb9, 0x82, 0x00, 0x23,	/* xgr %r2, %r3 */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_equal" emit_ops method for s390x.  */
+
+static void
+s390x_emit_equal (void)
+{
+  s390x_emit_bit_xor ();
+  s390x_emit_log_not ();
+}
+
+/* The "emit_less_signed" emit_ops method for s390x.  */
+
+static void
+s390x_emit_less_signed (void)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20,	/* cg %r2, 0(%r15) */
+    0xa7, 0x29, 0x00, 0x01,		/* lghi %r2, 1 */
+    0xa7, 0x24, 0x00, 0x04,		/* jh .Lend */
+    0xa7, 0x29, 0x00, 0x00,		/* lghi %r2, 0 */
+    /* .Lend: */
+    0x41, 0xf0, 0xf0, 0x08,		/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_less_unsigned" emit_ops method for s390x.  */
+
+static void
+s390x_emit_less_unsigned (void)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x21,	/* clg %r2, 0(%r15) */
+    0xa7, 0x29, 0x00, 0x01,		/* lghi %r2, 1 */
+    0xa7, 0x24, 0x00, 0x04,		/* jh .Lend */
+    0xa7, 0x29, 0x00, 0x00,		/* lghi %r2, 0 */
+    /* .Lend: */
+    0x41, 0xf0, 0xf0, 0x08,		/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_ref" emit_ops method for s390x.  */
+
+static void
+s390x_emit_ref (int size)
+{
+  static const unsigned char buf1[] = {
+    0xe3, 0x20, 0x20, 0x00, 0x00, 0x90,	/* llgc %r2, 0(%r2) */
+  };
+  static const unsigned char buf2[] = {
+    0xe3, 0x20, 0x20, 0x00, 0x00, 0x91	/* llgh %r2, 0(%r2) */
+  };
+  static const unsigned char buf4[] = {
+    0xe3, 0x20, 0x20, 0x00, 0x00, 0x16,	/* llgf %r2, 0(%r2) */
+  };
+  static const unsigned char buf8[] = {
+    0xe3, 0x20, 0x20, 0x00, 0x00, 0x04,	/* lg %r2, 0(%r2) */
+  };
+  switch (size)
+    {
+    case 1:
+      add_insns (buf1, sizeof buf1);
+      break;
+    case 2:
+      add_insns (buf2, sizeof buf2);
+      break;
+    case 4:
+      add_insns (buf4, sizeof buf4);
+      break;
+    case 8:
+      add_insns (buf8, sizeof buf8);
+      break;
+    default:
+      emit_error = 1;
+    }
+}
+
+/* The "emit_if_goto" emit_ops method for s390x.  */
+
+static void
+s390x_emit_if_goto (int *offset_p, int *size_p)
+{
+  static const unsigned char buf[] = {
+    0xb9, 0x02, 0x00, 0x22,		/* ltgr %r2, %r2 */
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x04,	/* lg %r2, 0(%r15) */
+    0x41, 0xf0, 0xf0, 0x08,		/* la %r15, 8(%r15) */
+    0xc0, 0x74, 0x00, 0x00, 0x00, 0x00,	/* jgne <fillme> */
+  };
+  add_insns (buf, sizeof buf);
+  if (offset_p)
+    *offset_p = 16;
+  if (size_p)
+    *size_p = 4;
+}
+
+/* The "emit_const" emit_ops method for s390x.  */
+
+static void
+s390x_emit_const (LONGEST num)
+{
+  unsigned long long n = num;
+  unsigned char buf_s[] = {
+    0xa7, 0x29, num >> 8, num,		/* lghi %r2, <num> */
+  };
+  static const unsigned char buf_l[] = {
+    0xe3, 0x20, 0x10, 0x00, 0x00, 0x04,	/* lg %r2, 0(%r1) */
+  };
+  if (num < 0x8000 && num >= -0x8000)
+  {
+    add_insns (buf_s, sizeof buf_s);
+  }
+  else
+  {
+    s390_emit_litpool (8);
+    add_insns ((unsigned char *) &n, sizeof n);
+    add_insns (buf_l, sizeof buf_l);
+  }
+}
+
+/* The "emit_call" emit_ops method for s390x.  */
+
+static void
+s390x_emit_call (CORE_ADDR fn)
+{
+  unsigned long n = fn;
+  static const unsigned char buf[] = {
+    0xe3, 0x10, 0x10, 0x00, 0x00, 0x04,	/* lg %r1, 0(%r1) */
+    0xa7, 0xfb, 0xff, 0x60,		/* aghi %r15, -0xa0 */
+    0x0d, 0xe1,				/* basr %r14, %r1 */
+    0xa7, 0xfb, 0x00, 0xa0,		/* aghi %r15, 0xa0 */
+  };
+  s390_emit_litpool (8);
+  add_insns ((unsigned char *) &n, sizeof n);
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_reg" emit_ops method for s390x.  */
+
+static void
+s390x_emit_reg (int reg)
+{
+  unsigned char buf[] = {
+    0xb9, 0x04, 0x00, 0x29,		/* lgr %r2, %r9 */
+    0xa7, 0x39, reg >> 8, reg,		/* lghi %r3, <reg> */
+  };
+  add_insns (buf, sizeof buf);
+  s390x_emit_call (get_raw_reg_func_addr ());
+}
+
+/* The "emit_pop" emit_ops method for s390x.  */
+
+static void
+s390x_emit_pop (void)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x04,	/* lg %r2, 0(%r15) */
+    0x41, 0xf0, 0xf0, 0x08,		/* la %r15, 8(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_stack_flush" emit_ops method for s390x.  */
+
+static void
+s390x_emit_stack_flush (void)
+{
+  static const unsigned char buf[] = {
+    0xa7, 0xfb, 0xff, 0xf8,		/* aghi %r15, -8 */
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x24,	/* stg %r2, 0(%r15) */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_zero_ext" emit_ops method for s390x.  */
+
+static void
+s390x_emit_zero_ext (int arg)
+{
+  unsigned char buf[] = {
+    0xeb, 0x22, 0x00, 64-arg, 0x00, 0x0d,	/* sllg %r2, %r2, <64-arg> */
+    0xeb, 0x22, 0x00, 64-arg, 0x00, 0x0c,	/* srlg %r2, %r2, <64-arg> */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_swap" emit_ops method for s390x.  */
+
+static void
+s390x_emit_swap (void)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x30, 0xf0, 0x00, 0x00, 0x04,	/* lg %r3, 0(%r15) */
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x24,	/* stg %r2, 0(%r15) */
+    0xb9, 0x04, 0x00, 0x23,		/* lgr %r2, %r3 */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_stack_adjust" emit_ops method for s390x.  */
+
+static void
+s390x_emit_stack_adjust (int n)
+{
+  unsigned char buf[] = {
+    0xa7, 0xfb, n * 8 >> 8, n * 8,	/* aghi %r15, 8*n */
+  };
+  add_insns (buf, sizeof buf);
+}
+
+/* The "emit_int_call_1" emit_ops method for s390x.  */
+
+static void
+s390x_emit_int_call_1 (CORE_ADDR fn, int arg1)
+{
+  /* FN's prototype is `LONGEST(*fn)(int)'.  */
+  s390x_emit_const (arg1);
+  s390x_emit_call (fn);
+}
+
+/* The "emit_void_call_2" emit_ops method for s390x.  */
+
+static void
+s390x_emit_void_call_2 (CORE_ADDR fn, int arg1)
+{
+  /* FN's prototype is `void(*fn)(int,LONGEST)'.  */
+  static const unsigned char buf[] = {
+    0xb9, 0x04, 0x00, 0x32,		/* lgr %r3, %r2 */
+    0xb9, 0x04, 0x00, 0xc2,		/* lgr %r12, %r2 */
+  };
+  static const unsigned char buf2[] = {
+    0xb9, 0x04, 0x00, 0x2c,		/* lgr %r2, %r12 */
+  };
+  add_insns (buf, sizeof buf);
+  s390x_emit_const (arg1);
+  s390x_emit_call (fn);
+  add_insns (buf2, sizeof buf2);
+}
+
+/* The "emit_eq_goto" emit_ops method for s390x.  */
+
+void
+s390x_emit_eq_goto (int *offset_p, int *size_p)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20,	/* cg %r2, 0(%r15) */
+    0xe3, 0x20, 0xf0, 0x08, 0x00, 0x04, /* lg %r2, 8(%r15) */
+    0x41, 0xf0, 0xf0, 0x10,		/* la %r15, 16(%r15) */
+    0xc0, 0x84, 0x00, 0x00, 0x00, 0x00,	/* jge <fillme> */
+  };
+  add_insns (buf, sizeof buf);
+  if (offset_p)
+    *offset_p = 18;
+  if (size_p)
+    *size_p = 4;
+}
+
+/* The "emit_ne_goto" emit_ops method for s390x.  */
+
+void
+s390x_emit_ne_goto (int *offset_p, int *size_p)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20,	/* cg %r2, 0(%r15) */
+    0xe3, 0x20, 0xf0, 0x08, 0x00, 0x04, /* lg %r2, 8(%r15) */
+    0x41, 0xf0, 0xf0, 0x10,		/* la %r15, 16(%r15) */
+    0xc0, 0x74, 0x00, 0x00, 0x00, 0x00,	/* jgne <fillme> */
+  };
+  add_insns (buf, sizeof buf);
+  if (offset_p)
+    *offset_p = 18;
+  if (size_p)
+    *size_p = 4;
+}
+
+/* The "emit_lt_goto" emit_ops method for s390x.  */
+
+void
+s390x_emit_lt_goto (int *offset_p, int *size_p)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20,	/* cg %r2, 0(%r15) */
+    0xe3, 0x20, 0xf0, 0x08, 0x00, 0x04, /* lg %r2, 8(%r15) */
+    0x41, 0xf0, 0xf0, 0x10,		/* la %r15, 16(%r15) */
+    0xc0, 0x24, 0x00, 0x00, 0x00, 0x00,	/* jgh <fillme> */
+  };
+  add_insns (buf, sizeof buf);
+  if (offset_p)
+    *offset_p = 18;
+  if (size_p)
+    *size_p = 4;
+}
+
+/* The "emit_le_goto" emit_ops method for s390x.  */
+
+void
+s390x_emit_le_goto (int *offset_p, int *size_p)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20,	/* cg %r2, 0(%r15) */
+    0xe3, 0x20, 0xf0, 0x08, 0x00, 0x04, /* lg %r2, 8(%r15) */
+    0x41, 0xf0, 0xf0, 0x10,		/* la %r15, 16(%r15) */
+    0xc0, 0xa4, 0x00, 0x00, 0x00, 0x00,	/* jghe <fillme> */
+  };
+  add_insns (buf, sizeof buf);
+  if (offset_p)
+    *offset_p = 18;
+  if (size_p)
+    *size_p = 4;
+}
+
+/* The "emit_gt_goto" emit_ops method for s390x.  */
+
+void
+s390x_emit_gt_goto (int *offset_p, int *size_p)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20,	/* cg %r2, 0(%r15) */
+    0xe3, 0x20, 0xf0, 0x08, 0x00, 0x04, /* lg %r2, 8(%r15) */
+    0x41, 0xf0, 0xf0, 0x10,		/* la %r15, 16(%r15) */
+    0xc0, 0x44, 0x00, 0x00, 0x00, 0x00,	/* jgl <fillme> */
+  };
+  add_insns (buf, sizeof buf);
+  if (offset_p)
+    *offset_p = 18;
+  if (size_p)
+    *size_p = 4;
+}
+
+/* The "emit_ge_goto" emit_ops method for s390x.  */
+
+void
+s390x_emit_ge_goto (int *offset_p, int *size_p)
+{
+  static const unsigned char buf[] = {
+    0xe3, 0x20, 0xf0, 0x00, 0x00, 0x20,	/* cg %r2, 0(%r15) */
+    0xe3, 0x20, 0xf0, 0x08, 0x00, 0x04, /* lg %r2, 8(%r15) */
+    0x41, 0xf0, 0xf0, 0x10,		/* la %r15, 16(%r15) */
+    0xc0, 0xc4, 0x00, 0x00, 0x00, 0x00,	/* jgle <fillme> */
+  };
+  add_insns (buf, sizeof buf);
+  if (offset_p)
+    *offset_p = 18;
+  if (size_p)
+    *size_p = 4;
+}
+
+/* The "emit_ops" structure for s390x.  */
+
+struct emit_ops s390x_emit_ops =
+  {
+    s390x_emit_prologue,
+    s390x_emit_epilogue,
+    s390x_emit_add,
+    s390x_emit_sub,
+    s390x_emit_mul,
+    s390x_emit_lsh,
+    s390x_emit_rsh_signed,
+    s390x_emit_rsh_unsigned,
+    s390x_emit_ext,
+    s390x_emit_log_not,
+    s390x_emit_bit_and,
+    s390x_emit_bit_or,
+    s390x_emit_bit_xor,
+    s390x_emit_bit_not,
+    s390x_emit_equal,
+    s390x_emit_less_signed,
+    s390x_emit_less_unsigned,
+    s390x_emit_ref,
+    s390x_emit_if_goto,
+    s390_emit_goto,
+    s390_write_goto_address,
+    s390x_emit_const,
+    s390x_emit_call,
+    s390x_emit_reg,
+    s390x_emit_pop,
+    s390x_emit_stack_flush,
+    s390x_emit_zero_ext,
+    s390x_emit_swap,
+    s390x_emit_stack_adjust,
+    s390x_emit_int_call_1,
+    s390x_emit_void_call_2,
+    s390x_emit_eq_goto,
+    s390x_emit_ne_goto,
+    s390x_emit_lt_goto,
+    s390x_emit_le_goto,
+    s390x_emit_gt_goto,
+    s390x_emit_ge_goto
+  };
+#endif
+
+/* The "emit_ops" linux_target_ops method.  */
+
+static struct emit_ops *
+s390_emit_ops (void)
+{
+#ifdef __s390x__
+  struct regcache *regcache = get_thread_regcache (current_thread, 0);
+
+  if (register_size (regcache->tdesc, 0) == 8)
+    return &s390x_emit_ops;
+  else
+#endif
+    return &s390_emit_ops_impl;
+}
+
 struct linux_target_ops the_low_target = {
   s390_arch_setup,
   s390_regs_info,
@@ -1426,7 +2770,7 @@ struct linux_target_ops the_low_target = {
   s390_supports_tracepoints,
   s390_get_thread_area,
   s390_install_fast_tracepoint_jump_pad,
-  NULL, /* emit_ops */
+  s390_emit_ops,
   s390_get_min_fast_tracepoint_insn_len,
   NULL, /* supports_range_stepping */
   NULL, /* breakpoint_kind_from_current_state */
-- 
2.7.1

  reply	other threads:[~2016-03-04 10:41 UTC|newest]

Thread overview: 89+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-01-24 12:12 [PATCH 0/8] gdb/s390: Add regular and fast tracepoint support Marcin Kościelnicki
2016-01-24 12:12 ` [PATCH 3/8] gdb/s390: Fill pseudo register agent expression hooks Marcin Kościelnicki
2016-02-07 14:01   ` Marcin Kościelnicki
2016-02-25 19:23     ` Marcin Kościelnicki
2016-03-04 10:42       ` Marcin Kościelnicki
2016-03-11  2:20         ` Marcin Kościelnicki
2016-03-11  9:58     ` Andreas Arnez
2016-03-11 10:04       ` Marcin Kościelnicki
2016-01-24 12:12 ` [PATCH 8/8] gdbserver/s390: Add support for compiled agent expressions Marcin Kościelnicki
2016-03-04 10:41   ` Marcin Kościelnicki [this message]
2016-03-14 16:19     ` [PATCH v2] " Andreas Arnez
2016-01-24 12:12 ` [PATCH 1/8] gdb: Add write_guessed_tracepoint_pc hook to gdbarch Marcin Kościelnicki
2016-01-26 14:58   ` Andreas Arnez
2016-02-07 13:59     ` [PATCH 1/8] gdb: Add supply_pseudo_pc " Marcin Kościelnicki
2016-02-16 18:28       ` Ulrich Weigand
2016-02-16 21:32         ` Marcin Kościelnicki
2016-02-18 10:35         ` [PATCH 1/2] gdb: Add guess_tracepoint_registers " Marcin Kościelnicki
2016-02-18 10:35           ` [PATCH 2/2] gdb/s390: Fill guess_tracepoint_registers hook Marcin Kościelnicki
2016-02-18 16:03             ` Ulrich Weigand
2016-02-18 16:36               ` [PATCH] " Marcin Kościelnicki
2016-02-18 16:48                 ` Ulrich Weigand
2016-02-18 16:58                   ` Marcin Kościelnicki
2016-02-18 11:38           ` [PATCH 1/2] gdb: Add guess_tracepoint_registers hook to gdbarch Luis Machado
2016-02-18 11:39             ` Marcin Kościelnicki
2016-02-18 11:45             ` [PATCH] " Marcin Kościelnicki
2016-02-18 15:40               ` Ulrich Weigand
2016-02-18 15:41                 ` Marcin Kościelnicki
2016-02-18 15:58                   ` Ulrich Weigand
2016-02-18 16:01                     ` Marcin Kościelnicki
2016-02-18 16:06                       ` Ulrich Weigand
2016-02-18 16:11                         ` Marcin Kościelnicki
2016-02-18 16:13                           ` Ulrich Weigand
2016-02-18 16:22                             ` Marcin Kościelnicki
2016-01-24 12:12 ` [PATCH 5/8] gdbserver/s390: Switch on tracepoint support Marcin Kościelnicki
2016-02-07 14:04   ` Marcin Kościelnicki
2016-02-22  7:38     ` [PATCH] " Marcin Kościelnicki
2016-03-04 10:39       ` [PATCH v3] " Marcin Kościelnicki
2016-03-15 18:41         ` [PATCH v4] " Marcin Kościelnicki
2016-03-22  9:16           ` Marcin Kościelnicki
2016-03-23 15:25           ` Andreas Arnez
2016-03-24  1:15             ` Marcin Kościelnicki
2016-03-29 18:31               ` Ulrich Weigand
2016-03-29 21:40                 ` Marcin Kościelnicki
2016-03-29 21:40             ` [PATCH obv] gdb/NEWS: Add mention of s390*-linux tracepoints Marcin Kościelnicki
2016-03-30  2:49               ` Eli Zaretskii
2016-01-24 12:12 ` [PATCH 7/8] gdb.trace: Bump tspeed.exp timeout to 600 seconds Marcin Kościelnicki
2016-01-26 18:17   ` Andreas Arnez
2016-01-29  9:53     ` [PATCH] " Marcin Kościelnicki
2016-02-12 11:20       ` Yao Qi
2016-02-18 18:54       ` Marcin Kościelnicki
2016-01-24 12:12 ` [PATCH 2/8] gdb/s390: Fill write_guessed_tracepoint_pc hook Marcin Kościelnicki
2016-01-26 18:12   ` Andreas Arnez
2016-01-26 19:26     ` Marcin Kościelnicki
2016-01-29 18:57       ` Andreas Arnez
2016-02-07 14:00         ` [PATCH 2/8] gdb/s390: Fill supply_pseudo_pc hook Marcin Kościelnicki
2016-01-24 12:12 ` [PATCH 4/8] gdb/s390: Fill gen_return_address hook Marcin Kościelnicki
2016-02-07 14:02   ` Marcin Kościelnicki
2016-02-25 19:23     ` Marcin Kościelnicki
2016-03-04 10:42       ` Marcin Kościelnicki
2016-03-11 11:20     ` Andreas Arnez
2016-03-11 11:35       ` Marcin Kościelnicki
2016-03-11 12:18         ` Andreas Arnez
2016-03-11 12:26           ` Marcin Kościelnicki
2016-03-11 15:31             ` Andreas Arnez
2016-03-11 15:44               ` Pedro Alves
2016-03-11 16:45                 ` Andreas Arnez
2016-03-11 17:02                   ` Pedro Alves
2016-03-11 18:17                     ` Eli Zaretskii
2016-03-11 18:37                       ` Pedro Alves
2016-03-11 19:34                         ` Eli Zaretskii
2016-03-15 11:11                           ` Pedro Alves
2016-03-15 11:23                             ` Andreas Arnez
2016-03-15 11:30                               ` Pedro Alves
2016-03-11 18:07                   ` Eli Zaretskii
2016-03-13  9:53               ` Marcin Kościelnicki
2016-03-14 10:07                 ` Andreas Arnez
2016-01-24 12:13 ` [PATCH 6/8] gdbserver/s390: Add fast tracepoint support Marcin Kościelnicki
2016-01-25 14:34   ` Antoine Tremblay
2016-02-19 13:41     ` Marcin Kościelnicki
2016-02-19 14:41       ` Antoine Tremblay
2016-03-04 10:40         ` [PATCH v2] " Marcin Kościelnicki
2016-03-14 16:19           ` Andreas Arnez
2016-03-14 16:25             ` Marcin Kościelnicki
2016-01-25 13:27 ` [PATCH 0/8] gdb/s390: Add regular and " Antoine Tremblay
2016-01-25 13:56 ` Pedro Alves
2016-01-25 14:28   ` Marcin Kościelnicki
2016-01-25 15:57     ` Pedro Alves
2016-01-25 16:03       ` Marcin Kościelnicki
2016-02-12 11:04 ` Marcin Kościelnicki

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1457088067-3197-1-git-send-email-koriakin@0x04.net \
    --to=koriakin@0x04.net \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).