--- coregrind/m_syswrap/syswrap-amd64-openbsd.c.orig
+++ coregrind/m_syswrap/syswrap-amd64-openbsd.c
@@ -0,0 +1,943 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Platform-specific syscalls stuff.    syswrap-amd64-openbsd.c ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+   This file is part of Valgrind, a dynamic binary instrumentation
+   framework.
+
+   Copyright (C) 2000-2005 Nicholas Nethercote
+      njn@valgrind.org
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307, USA.
+
+   The GNU General Public License is contained in the file COPYING.
+*/
+
+#if defined(VGP_amd64_openbsd)
+
+#include "pub_core_basics.h"
+#include "pub_core_vki.h"
+#include "pub_core_vkiscnums.h"
+#include "pub_core_libcsetjmp.h"    // to keep _threadstate.h happy
+#include "pub_core_threadstate.h"
+#include "pub_core_aspacemgr.h"
+#include "pub_core_debuglog.h"
+#include "pub_core_libcbase.h"
+#include "pub_core_libcassert.h"
+#include "pub_core_libcprint.h"
+#include "pub_core_libcproc.h"
+#include "pub_core_libcsignal.h"
+#include "pub_core_machine.h"
+#include "pub_core_options.h"
+#include "pub_core_scheduler.h"
+#include "pub_core_sigframe.h"
+#include "pub_core_signals.h"
+#include "pub_core_syscall.h"
+#include "pub_core_syswrap.h"
+#include "pub_core_tooliface.h"
+#include "pub_core_stacks.h"        // VG_(register_stack)
+
+#include "pub_tool_libcbase.h"
+
+#include "priv_types_n_macros.h"
+#include "priv_syswrap-generic.h"    /* for decls of generic wrappers */
+#include "priv_syswrap-openbsd.h"    /* for decls of openbsd-ish wrappers */
+#include "priv_syswrap-main.h"
+
+/* ---------------------------------------------------------------------
+   clone() handling
+   ------------------------------------------------------------------ */
+
+/* Call f(arg1), but first switch stacks, using 'stack' as the new
+   stack, and use 'retaddr' as f's return-to address.  Also, clear all
+   the integer registers before entering f. */
+__attribute__((noreturn))
+void ML_(call_on_new_stack_0_1) ( Addr stack,
+                                  Addr retaddr,
+                                  void (*f)(Word),
+                                  Word arg1 );
+// %rdi == stack
+// %rsi == retaddr
+// %rdx == f
+// %rcx == arg1
+__asm__(
+   ".text\n"
+   ".globl vgModuleLocal_call_on_new_stack_0_1\n"
+   "vgModuleLocal_call_on_new_stack_0_1:\n"
+   "   movq   %rdi, %rsp\n"   // set stack
+   "   pushq  %rsi\n"         // retaddr to stack
+   "   pushq  %rdx\n"         // f to stack
+   "   pushq  %rcx\n"         // arg1 to stack
+   "   movq $0, %rax\n"       // zero all GP regs
+   "   movq $0, %rbx\n"
+   "   movq $0, %rcx\n"
+   "   movq $0, %rdx\n"
+   "   movq $0, %rsi\n"
+   "   movq $0, %rdi\n"
+   "   movq $0, %rbp\n"
+   "   movq $0, %r8\n"
+   "   movq $0, %r9\n"
+   "   movq $0, %r10\n"
+   "   movq $0, %r11\n"
+   "   movq $0, %r12\n"
+   "   movq $0, %r13\n"
+   "   movq $0, %r14\n"
+   "   movq $0, %r15\n"
+   "   popq   %rdi\n"         // arg1 to correct arg reg
+   "   ret\n"                 // jump to f
+   "   ud2\n"                 // should never get here
+   ".previous\n"
+);
+
+
+/* ---------------------------------------------------------------------
+   More thread stuff
+   ------------------------------------------------------------------ */
+
+void VG_(cleanup_thread) ( ThreadArchState *arch )
+{
+}
+
+/* ---------------------------------------------------------------------
+   PRE/POST wrappers for amd64/OpenBSD-specific syscalls
+   ------------------------------------------------------------------ */
+
+#define PRE(name)       DEFN_PRE_TEMPLATE(openbsd, name)
+#define POST(name)      DEFN_POST_TEMPLATE(openbsd, name)
+
+extern UWord do_syscall_tfork_amd64_openbsd (
+	  Addr params,
+	  UWord psize,
+	  Addr startfunc,
+	  Addr startarg);
+asm(
+".text\n"
+".globl do_syscall_tfork_amd64_openbsd\n"
+"do_syscall_tfork_amd64_openbsd:\n"
+	/* Copy %rdx to %r8 and %rcx to %r9.  See:
+	   - lib/libc/arch/amd64/sys/tfork_thread.S */
+"	movq	%rdx, %r8\n"
+"	movq	%rcx, %r9\n"
+"	movq	$8, %rax\n"		/* syscall_no */
+"	syscall\n"
+"	jb	5f\n"			/* error */
+	/*
+	 * Check to see if we are in the parent or child
+	 */
+"	cmpl	$0, %eax\n"
+"	jz	4f\n"			/* child */
+"	jmp	5f\n"			/* parent */
+	/* the retpoline we'll use to call the child's main */
+".align	16, 0xcc\n"			/* _ALIGN_TRAPS */
+"1:\n"					/* JMP_RETPOLINE(r8) --> */
+"	call	3f\n"
+"2:	pause\n"
+"	lfence\n"
+"	jmp	2b\n"
+".align	16, 0xcc\n"			/* _ALIGN_TRAPS */
+"3:	mov	%r8,(%rsp)\n"
+"	ret\n"
+					/* JMP_RETPOLINE(r8) <-- */
+	/*
+	 * If we are in the child (new thread), then
+	 * set-up the call to the internal subroutine.	If it
+	 * returns, then call __threxit.
+	 */
+".align	16, 0xcc\n"			/* _ALIGN_TRAPS */
+"4:\n"
+"	movq	%r9, %rdi\n"
+"	call	1b\n"
+	/*
+	 * Thread exit system call
+	 */
+"	movl	$302, %eax\n"		/* 302 == SYS___threxit */
+"	xorl	%edi, %edi\n"
+"	syscall\n"
+	/*NOTREACHED*/
+"5:\n"					/* parent or error */
+"	ret\n"
+".previous\n"
+);
+
+static void setup_child ( ThreadArchState*, ThreadArchState* );
+
+void setup_child ( /*OUT*/ ThreadArchState *child,
+                   /*IN*/  ThreadArchState *parent )
+{
+   /* We inherit our parent's guest state. */
+   child->vex = parent->vex;
+   child->vex_shadow1 = parent->vex_shadow1;
+   child->vex_shadow2 = parent->vex_shadow2;
+}
+
+/*
+   When a client clones, we need to keep track of the new thread.  This means:
+   1. allocate a ThreadId+ThreadState+stack for the the thread
+
+   2. initialize the thread's new VCPU state
+
+   3. create the thread using the same args as the client requested,
+   but using the scheduler entrypoint for EIP, and a separate stack
+   for ESP.
+
+   This function was implemented with reference to the syswrap-amd64-linux.c:
+   do_clone() function.
+ */
+static SysRes do_tfork ( ThreadId ptid,
+                         Addr params,
+                         ULong psize,
+                         Addr startfunc,
+                         Addr startarg)
+{
+   ThreadId     ctid = VG_(alloc_ThreadState)();
+   ThreadState* ptst = VG_(get_ThreadState)(ptid);
+   ThreadState* ctst = VG_(get_ThreadState)(ctid);
+   UWord*       stack;
+   SysRes       res;
+   Long         rax;
+   vki_sigset_t blockall, savedmask;
+   struct __vki_tfork * tfork;
+
+   VG_(sigfillset)(&blockall);
+
+   vg_assert(params != 0);
+   vg_assert(psize > 0);
+   vg_assert(startfunc != 0);
+   vg_assert(VG_(is_running_thread)(ptid));
+   vg_assert(VG_(is_valid_tid)(ctid));
+
+   stack = (UWord*)ML_(allocstack)(ctid);
+   if (stack == NULL) {
+      res = VG_(mk_SysRes_Error)( VKI_ENOMEM );
+      goto out;
+   }
+
+   /* Copy register state
+
+      Both parent and child return to the same place, and the code
+      following the __tfork syscall works out which is which, so we
+      don't need to worry about it.
+
+      The parent gets the child's new tid returned from clone, but the
+      child gets 0.
+
+      If the clone call specifies a NULL tfork->tf_stack for the new thread,
+      then it actually gets a copy of the parent's rsp.
+   */
+   setup_child( &ctst->arch, &ptst->arch );
+
+   /* Make sys___tfork appear to have returned Success(0) in the
+      child. */
+   ctst->arch.vex.guest_RAX = 0;
+
+   tfork = (struct __vki_tfork *)params;
+   vg_assert(tfork->tf_stack != 0);
+   ctst->arch.vex.guest_RSP = (ULong) tfork->tf_stack;
+   tfork->tf_stack = stack;
+
+   ctst->os_state.parent = ptid;
+
+   /* inherit signal mask */
+   ctst->sig_mask = ptst->sig_mask;
+   ctst->tmp_sig_mask = ptst->sig_mask;
+
+   /* Start the child with its threadgroup being the same as the
+      parent's.  This is so that any exit_group calls that happen
+      after the child is created but before it sets its
+      os_state.threadgroup field for real (in thread_wrapper in
+      syswrap-linux.c), really kill the new thread.  a.k.a this avoids
+      a race condition in which the thread is unkillable (via
+      exit_group) because its threadgroup is not set.  The race window
+      is probably only a few hundred or a few thousand cycles long.
+      See #226116. */
+   ctst->os_state.threadgroup = ptst->os_state.threadgroup;
+
+   ML_(guess_and_register_stack) ((Addr)tfork->tf_stack, ctst);
+
+   /* Assume the clone will succeed, and tell any tool that wants to
+      know that this thread has come into existence.  If the clone
+      fails, we'll send out a ll_exit notification for it at the out:
+      label below, to clean up. */
+   vg_assert(VG_(owns_BigLock_LL)(ptid));
+   VG_TRACK ( pre_thread_ll_create, ptid, ctid );
+
+   /* start the thread with everything blocked */
+   VG_(sigprocmask)(VKI_SIG_SETMASK, &blockall, &savedmask);
+
+   /* Create the new thread */
+   rax = do_syscall_tfork_amd64_openbsd(
+            params, psize, ML_(start_thread_NORETURN), &VG_(threads)[ctid]);
+   res = VG_(mk_SysRes_amd64_openbsd)( rax, ptst->arch.vex.guest_RDX,
+				       (rax == -1) ? True : False );
+
+   VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL);
+
+  out:
+   if (sr_isError(res)) {
+      /* clone failed */
+      VG_(cleanup_thread)(&ctst->arch);
+      ctst->status = VgTs_Empty;
+      /* oops.  Better tell the tool the thread exited in a hurry :-) */
+      VG_TRACK( pre_thread_ll_exit, ctid );
+   }
+
+   return res;
+}
+
+PRE(sys___tfork)
+{
+   struct __vki_tfork * tfork;
+   PRINT("sys___tfork ( %#lx, %ld, %#lx, %#lx )",ARG1,ARG2,ARG3,ARG4);
+   PRE_REG_READ4(long, "__tfork", struct __tfork *, params, size_t, psize,
+ 		 void (*)(void *), startfunc, void *, startarg);
+   PRE_MEM_READ( "__tfork(params, psize)", ARG1, ARG2 );
+   tfork = (struct __vki_tfork *)ARG1;
+   if (tfork->tf_tid != NULL)
+      PRE_MEM_READ("__tfork(params.tf_tid)", (Addr)tfork->tf_tid,
+		   sizeof (pid_t));
+   SET_STATUS_from_SysRes(
+      do_tfork(tid, (Addr)ARG1, (ULong)ARG2, (Addr)ARG3, (Addr)ARG4));
+
+   if (SUCCESS) {
+      POST_MEM_WRITE((Addr)tfork->tf_tcb, sizeof (void *));
+      POST_MEM_WRITE((Addr)tfork->tf_tid, sizeof (pid_t));
+
+      /* Thread creation was successful; let the child have the chance
+         to run */
+      *flags |= SfYieldAfter;
+   }
+}
+
+#if 0
+PRE(sys_thr_new)
+{
+   static const Bool debug = False;
+
+   ThreadId     ctid = VG_(alloc_ThreadState)();
+   ThreadState* ptst = VG_(get_ThreadState)(tid);
+   ThreadState* ctst = VG_(get_ThreadState)(ctid);
+   SysRes       res;
+   vki_sigset_t blockall, savedmask;
+   struct vki_thr_param tp;
+   Addr stk;
+
+   PRINT("thr_new ( %#lx, %ld )",ARG1,ARG2);
+   PRE_REG_READ2(int, "thr_new",
+                 struct thr_param *, param,
+                 int, param_size);
+   
+   PRE_MEM_READ( "thr_new(param)", ARG1, offsetof(struct vki_thr_param, spare));
+   if (!ML_(safe_to_deref)( (void*)ARG1, offsetof(struct vki_thr_param, spare))) {
+      SET_STATUS_Failure( VKI_EFAULT );
+      return;
+   }
+   VG_(memset)(&tp, 0, sizeof(tp));
+   VG_(memcpy)(&tp, (void *)ARG1, offsetof(struct vki_thr_param, spare));
+   PRE_MEM_WRITE("thr_new(parent_tidptr)", (Addr)tp.parent_tid, sizeof(long));
+   PRE_MEM_WRITE("thr_new(child_tidptr)", (Addr)tp.child_tid, sizeof(long));
+
+   VG_(sigfillset)(&blockall);
+
+   vg_assert(VG_(is_running_thread)(tid));
+   vg_assert(VG_(is_valid_tid)(ctid));
+
+   /* Copy register state
+
+      On linux, both parent and child return to the same place, and the code
+      following the clone syscall works out which is which, so we
+      don't need to worry about it.
+      On FreeBSD, thr_new arranges a direct call.  We don't actually need any
+      of this gunk.
+
+      The parent gets the child's new tid returned from clone, but the
+      child gets 0.
+
+      If the clone call specifies a NULL rsp for the new thread, then
+      it actually gets a copy of the parent's rsp.
+   */
+   /* We inherit our parent's guest state. */
+   ctst->arch.vex = ptst->arch.vex;
+   ctst->arch.vex_shadow1 = ptst->arch.vex_shadow1;
+   ctst->arch.vex_shadow2 = ptst->arch.vex_shadow2;
+
+   /* Make thr_new appear to have returned Success(0) in the
+      child. */
+   ctst->arch.vex.guest_RAX = 0;
+   ctst->arch.vex.guest_RDX = 0;
+   LibVEX_GuestAMD64_put_rflag_c(0, &ctst->arch.vex);
+
+   ctst->os_state.parent = tid;
+
+   /* inherit signal mask */
+   ctst->sig_mask = ptst->sig_mask;
+   ctst->tmp_sig_mask = ptst->sig_mask;
+
+   /* Linux has to guess, we don't */
+   ctst->client_stack_highest_word = (Addr)tp.stack_base + tp.stack_size;
+   ctst->client_stack_szB = tp.stack_size;
+   VG_(register_stack)((Addr)tp.stack_base, (Addr)tp.stack_base + tp.stack_size);
+
+   /* Assume the thr_new will succeed, and tell any tool that wants to
+      know that this thread has come into existence.  If the thr_new
+      fails, we'll send out a ll_exit notification for it at the out:
+      label below, to clean up. */
+   VG_TRACK ( pre_thread_ll_create, tid, ctid );
+
+   if (debug)
+      VG_(printf)("clone child has SETTLS: tls at %#lx\n", (Addr)tp.tls_base);
+   ctst->arch.vex.guest_FS_ZERO = (UWord)tp.tls_base;
+   tp.tls_base = 0;	/* Don't have the kernel do it too */
+
+   /* start the thread with everything blocked */
+   VG_(sigprocmask)(VKI_SIG_SETMASK, &blockall, &savedmask);
+
+   /* Set the client state for scheduler to run libthr's trampoline */
+   ctst->arch.vex.guest_RDI = (Addr)tp.arg;
+   /* XXX: align on 16-byte boundary? */
+   ctst->arch.vex.guest_RSP = (Addr)tp.stack_base + tp.stack_size - 8;
+   ctst->arch.vex.guest_RIP = (Addr)tp.start_func;
+
+   /* But this is for thr_new() to run valgrind's trampoline */
+   tp.start_func = (void *)ML_(start_thread_NORETURN);
+   tp.arg = &VG_(threads)[ctid];
+
+   /* And valgrind's trampoline on its own stack */
+   stk = ML_(allocstack)(ctid);
+   if (stk == (Addr)NULL) {
+      res = VG_(mk_SysRes_Error)( VKI_ENOMEM );
+      goto fail;
+   }
+   tp.stack_base = (void *)ctst->os_state.valgrind_stack_base;
+   tp.stack_size = (Addr)stk - (Addr)tp.stack_base;
+
+   /* Create the new thread */
+   // XXX: Find solution for libthr
+   // res = VG_(do_syscall2)(__NR_thr_new, (UWord)&tp, sizeof(tp));
+
+   VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL);
+
+fail:
+   if (sr_isError(res)) {
+      /* thr_new failed */
+      VG_(cleanup_thread)(&ctst->arch);
+      ctst->status = VgTs_Empty;
+      /* oops.  Better tell the tool the thread exited in a hurry :-) */
+      VG_TRACK( pre_thread_ll_exit, ctid );
+   } else {
+
+      POST_MEM_WRITE((Addr)tp.parent_tid, sizeof(long));
+      POST_MEM_WRITE((Addr)tp.child_tid, sizeof(long));
+
+      /* Thread creation was successful; let the child have the chance
+         to run */
+      *flags |= SfYieldAfter;
+   }
+
+   /* "Complete" the syscall so that the wrapper doesn't call the kernel again. */
+   SET_STATUS_from_SysRes(res);
+}
+#endif
+
+#if 0
+PRE(sys_rfork)
+{
+   PRINT("sys_rfork ( %#lx )", ARG1 );
+   PRE_REG_READ1(long, "rfork", int, flags);
+
+   VG_(message)(Vg_UserMsg, "rfork() not implemented");
+   VG_(unimplemented)("Valgrind does not support rfork().");
+
+   SET_STATUS_Failure(VKI_ENOSYS);
+}
+#endif
+
+PRE(sys_sigreturn)
+{
+   PRINT("sys_sigreturn ( %#lx )", ARG1);
+   PRE_REG_READ1(long, "sigreturn",
+                 struct vki_ucontext *, ucp);
+
+   PRE_MEM_READ( "sigreturn(ucp)", ARG1, sizeof(struct vki_ucontext) );
+   PRE_MEM_WRITE( "sigreturn(ucp)", ARG1, sizeof(struct vki_ucontext) );
+}
+
+PRE(sys_fake_sigreturn)
+{
+   ThreadState* tst;
+   struct vki_ucontext *uc;
+   int rflags;
+
+   PRINT("sys_sigreturn ( %#lx )", ARG1);
+   PRE_REG_READ1(long, "sigreturn",
+                 struct vki_ucontext *, ucp);
+
+   PRE_MEM_READ( "sigreturn(ucp)", ARG1, sizeof(struct vki_ucontext) );
+   PRE_MEM_WRITE( "sigreturn(ucp)", ARG1, sizeof(struct vki_ucontext) );
+
+   vg_assert(VG_(is_valid_tid)(tid));
+   vg_assert(tid >= 1 && tid < VG_N_THREADS);
+   vg_assert(VG_(is_running_thread)(tid));
+
+   /* Adjust esp to point to start of frame; skip back up over handler
+      ret addr */
+   tst = VG_(get_ThreadState)(tid);
+   tst->arch.vex.guest_RSP -= sizeof(Addr);
+
+   uc = (struct vki_ucontext *)ARG1;
+   if (uc == NULL || uc->uc_mcontext.len != sizeof(uc->uc_mcontext)) {
+      SET_STATUS_Failure(VKI_EINVAL);
+      return;
+   }
+ 
+   /* This is only so that the EIP is (might be) useful to report if
+      something goes wrong in the sigreturn */
+   ML_(fixup_guest_state_to_restart_syscall)(&tst->arch);
+
+   VG_(sigframe_destroy)(tid);
+
+   /* For unclear reasons, it appears we need the syscall to return
+      without changing %EAX.  Since %EAX is the return value, and can
+      denote either success or failure, we must set up so that the
+      driver logic copies it back unchanged.  Also, note %EAX is of
+      the guest registers written by VG_(sigframe_destroy). */
+   rflags = LibVEX_GuestAMD64_get_rflags(&tst->arch.vex);
+   SET_STATUS_from_SysRes( VG_(mk_SysRes_amd64_openbsd)( tst->arch.vex.guest_RAX,
+       tst->arch.vex.guest_RDX, (rflags & 1) != 0 ? True : False) );
+
+   /*
+    * Signal handler might have changed the signal mask.  Respect that.
+    */
+   tst->sig_mask = uc->uc_sigmask;
+   tst->tmp_sig_mask = uc->uc_sigmask;
+
+   /* Tell the driver not to update the guest state with the "result",
+      and set a bogus result to keep it happy. */
+   *flags |= SfNoWriteResult;
+   SET_STATUS_Success(0);
+
+   /* Check to see if some any signals arose as a result of this. */
+   *flags |= SfPollAfter;
+}
+
+static void restore_mcontext(ThreadState *tst, struct vki_mcontext *sc)
+{
+   tst->arch.vex.guest_RAX     = sc->rax;
+   tst->arch.vex.guest_RCX     = sc->rcx;
+   tst->arch.vex.guest_RDX     = sc->rdx;
+   tst->arch.vex.guest_RBX     = sc->rbx;
+   tst->arch.vex.guest_RBP     = sc->rbp;
+   tst->arch.vex.guest_RSP     = sc->rsp;
+   tst->arch.vex.guest_RSI     = sc->rsi;
+   tst->arch.vex.guest_RDI     = sc->rdi;
+   tst->arch.vex.guest_R8      = sc->r8;
+   tst->arch.vex.guest_R9      = sc->r9;
+   tst->arch.vex.guest_R10     = sc->r10;
+   tst->arch.vex.guest_R11     = sc->r11;
+   tst->arch.vex.guest_R12     = sc->r12;
+   tst->arch.vex.guest_R13     = sc->r13;
+   tst->arch.vex.guest_R14     = sc->r14;
+   tst->arch.vex.guest_R15     = sc->r15;
+   tst->arch.vex.guest_RIP     = sc->rip;
+   /*
+    * XXX: missing support for other flags.
+    */
+   if (sc->rflags & 0x0001)
+      LibVEX_GuestAMD64_put_rflag_c(1, &tst->arch.vex);
+   else
+      LibVEX_GuestAMD64_put_rflag_c(0, &tst->arch.vex);
+}
+
+static void fill_mcontext(ThreadState *tst, struct vki_mcontext *sc)
+{
+   sc->rax = tst->arch.vex.guest_RAX;
+   sc->rcx = tst->arch.vex.guest_RCX;
+   sc->rdx = tst->arch.vex.guest_RDX;
+   sc->rbx = tst->arch.vex.guest_RBX;
+   sc->rbp = tst->arch.vex.guest_RBP;
+   sc->rsp = tst->arch.vex.guest_RSP;
+   sc->rsi = tst->arch.vex.guest_RSI;
+   sc->rdi = tst->arch.vex.guest_RDI;
+   sc->r8 = tst->arch.vex.guest_R8;
+   sc->r9 = tst->arch.vex.guest_R9;
+   sc->r10 = tst->arch.vex.guest_R10;
+   sc->r11 = tst->arch.vex.guest_R11;
+   sc->r12 = tst->arch.vex.guest_R12;
+   sc->r13 = tst->arch.vex.guest_R13;
+   sc->r14 = tst->arch.vex.guest_R14;
+   sc->r15 = tst->arch.vex.guest_R15;
+   sc->rip = tst->arch.vex.guest_RIP;
+/*
+   Not supported by VEX.
+   sc->cs = tst->arch.vex.guest_CS;
+   sc->ss = tst->arch.vex.guest_SS;
+   sc->ds = tst->arch.vex.guest_DS;
+   sc->es = tst->arch.vex.guest_ES;
+   sc->fs = tst->arch.vex.guest_FS;
+   sc->gs = tst->arch.vex.guest_GS;
+*/
+   sc->rflags = LibVEX_GuestAMD64_get_rflags(&tst->arch.vex);
+/*
+   not yet.
+   VG_(memcpy)(&sc->fpstate, fpstate, sizeof(*fpstate));
+*/
+   sc->fpformat = VKI_FPFMT_NODEV;
+   sc->ownedfp = VKI_FPOWNED_NONE;
+   sc->len = sizeof(*sc);
+   VG_(memset)(sc->spare2, 0, sizeof(sc->spare2));
+}
+
+PRE(sys_getcontext)
+{
+   ThreadState* tst;
+   struct vki_ucontext *uc;
+
+   PRINT("sys_getcontext ( %#lx )", ARG1);
+   PRE_REG_READ1(long, "getcontext",
+                 struct vki_ucontext *, ucp);
+   PRE_MEM_WRITE( "getcontext(ucp)", ARG1, sizeof(struct vki_ucontext) );
+   uc = (struct vki_ucontext *)ARG1;
+   if (uc == NULL) {
+      SET_STATUS_Failure(VKI_EINVAL);
+      return;
+   }
+   tst = VG_(get_ThreadState)(tid);
+   fill_mcontext(tst, &uc->uc_mcontext);
+   uc->uc_mcontext.rax = 0;
+   uc->uc_mcontext.rdx = 0;
+   uc->uc_mcontext.rflags &= ~0x0001;	/* PSL_C */
+   uc->uc_sigmask = tst->sig_mask;
+   VG_(memset)(uc->__spare__, 0, sizeof(uc->__spare__));
+   SET_STATUS_Success(0);
+}
+
+PRE(sys_setcontext)
+{
+   ThreadState* tst;
+   struct vki_ucontext *uc;
+
+   PRINT("sys_setcontext ( %#lx )", ARG1);
+   PRE_REG_READ1(long, "setcontext",
+                 struct vki_ucontext *, ucp);
+
+   PRE_MEM_READ( "setcontext(ucp)", ARG1, sizeof(struct vki_ucontext) );
+   PRE_MEM_WRITE( "setcontext(ucp)", ARG1, sizeof(struct vki_ucontext) );
+
+   vg_assert(VG_(is_valid_tid)(tid));
+   vg_assert(tid >= 1 && tid < VG_N_THREADS);
+   vg_assert(VG_(is_running_thread)(tid));
+
+   tst = VG_(get_ThreadState)(tid);
+   uc = (struct vki_ucontext *)ARG1;
+   if (uc == NULL || uc->uc_mcontext.len != sizeof(uc->uc_mcontext)) {
+      SET_STATUS_Failure(VKI_EINVAL);
+      return;
+   }
+ 
+   restore_mcontext(tst, &uc->uc_mcontext);
+   tst->sig_mask = uc->uc_sigmask;
+
+   /* Tell the driver not to update the guest state with the "result",
+      and set a bogus result to keep it happy. */
+   *flags |= SfNoWriteResult;
+   SET_STATUS_Success(0);
+
+   /* Check to see if some any signals arose as a result of this. */
+   *flags |= SfPollAfter;
+}
+
+PRE(sys_swapcontext)
+{
+   struct vki_ucontext *ucp, *oucp;
+   ThreadState* tst;
+
+   PRINT("sys_swapcontext ( %#lx, %#lx )", ARG1, ARG2);
+   PRE_REG_READ2(long, "swapcontext",
+                 struct vki_ucontext *, oucp, struct vki_ucontext *, ucp);
+
+   PRE_MEM_READ( "swapcontext(ucp)", ARG2, sizeof(struct vki_ucontext) );
+   PRE_MEM_WRITE( "swapcontext(oucp)", ARG1, sizeof(struct vki_ucontext) );
+
+   oucp = (struct vki_ucontext *)ARG1;
+   ucp = (struct vki_ucontext *)ARG2;
+   if (oucp == NULL || ucp == NULL || ucp->uc_mcontext.len != sizeof(ucp->uc_mcontext)) {
+      SET_STATUS_Failure(VKI_EINVAL);
+      return;
+   }
+   tst = VG_(get_ThreadState)(tid);
+
+   /*
+    * Save the context.
+    */
+   fill_mcontext(tst, &oucp->uc_mcontext);
+   oucp->uc_mcontext.rax = 0;
+   oucp->uc_mcontext.rdx = 0;
+   oucp->uc_mcontext.rflags &= ~0x0001;	/* PSL_C */
+   oucp->uc_sigmask = tst->sig_mask;
+   VG_(memset)(oucp->__spare__, 0, sizeof(oucp->__spare__));
+
+   /*
+    * Switch to new one.
+    */
+   restore_mcontext(tst, &ucp->uc_mcontext);
+   tst->sig_mask = ucp->uc_sigmask;
+
+   /* Tell the driver not to update the guest state with the "result",
+      and set a bogus result to keep it happy. */
+   *flags |= SfNoWriteResult;
+   SET_STATUS_Success(0);
+
+   /* Check to see if some any signals arose as a result of this. */
+   *flags |= SfPollAfter;
+}
+
+/* caddr_t mmap(caddr_t addr, size_t len, int prot, int flags, int fd, off_t pos); */
+/*              ARG1           ARG2       ARG3      ARG4       ARG5    ARG6 */
+
+PRE(sys_mmap)
+{
+   SysRes r;
+
+   PRINT("sys_mmap ( %#lx, %lu, %ld, %ld, %ld, 0x%lx)",
+         ARG1, (UWord)ARG2, ARG3, ARG4, ARG5, ARG6 );
+   PRE_REG_READ6(long, "mmap",
+                 void *, addr, vki_size_t, len, int, prot,  int, flags,
+                 int, fd, vki_off_t, pos);
+
+   r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 );
+   SET_STATUS_from_SysRes(r);
+}
+
+#if 0
+/* FreeBSD-7 introduces a "regular" version of mmap etc. */
+PRE(sys_mmap7)
+{
+   SysRes r;
+
+   PRINT("sys_mmap ( %#lx, %lu, %ld, %ld, %ld, 0x%lx)",
+         ARG1, (UWord)ARG2, ARG3, ARG4, ARG5, ARG6 );
+   PRE_REG_READ6(long, "mmap",
+                 char *, addr, unsigned long, len, int, prot,  int, flags,
+                 int, fd,  unsigned long, pos);
+
+   r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 );
+   SET_STATUS_from_SysRes(r);
+}
+#endif
+
+PRE(sys_lseek)
+{
+   PRINT("sys_lseek ( %ld, 0x%lx, %ld )", ARG1,ARG2,ARG3);
+
+#if !defined(VGO_openbsd)
+   PRE_REG_READ4(long, "lseek",
+                 unsigned int, fd, int, pad, unsigned long, offset,
+                 unsigned int, whence);
+#else
+   PRE_REG_READ3(long, "lseek",
+                 int, fd, vki_off_t, offset, int, whence);
+#endif
+}
+
+#if 0
+PRE(sys_lseek7)
+{
+   PRINT("sys_lseek ( %ld, 0x%lx, %ld )", ARG1,ARG2,ARG3);
+   PRE_REG_READ3(long, "lseek",
+                 unsigned int, fd, unsigned long, offset,
+                 unsigned int, whence);
+}
+#endif
+
+PRE(sys_pread)
+{
+   *flags |= SfMayBlock;
+   PRINT("sys_pread ( %ld, %#lx, %lu, %lu )", ARG1, ARG2, ARG3, ARG4);
+   PRE_REG_READ4(ssize_t, "pread",
+                 int, d, void *, buf, vki_size_t, nbytes, vki_off_t, offset);
+
+   if (!ML_(fd_allowed)(ARG1, "pread", tid, False))
+      SET_STATUS_Failure( VKI_EBADF );
+   else
+      PRE_MEM_WRITE( "pread(buf)", ARG2, ARG3 );
+}
+
+POST(sys_pread)
+{
+   vg_assert(SUCCESS);
+   POST_MEM_WRITE( ARG2, RES );
+}
+
+#if 0
+PRE(sys_pread7)
+{
+   *flags |= SfMayBlock;
+   PRINT("sys_read ( %ld, %#lx, %lu, %lu )", ARG1, ARG2, ARG3, ARG4);
+   PRE_REG_READ4(ssize_t, "read",
+                 unsigned int, fd, char *, buf, vki_size_t, count,
+                 unsigned long, off);
+
+   if (!ML_(fd_allowed)(ARG1, "read", tid, False))
+      SET_STATUS_Failure( VKI_EBADF );
+   else
+      PRE_MEM_WRITE( "read(buf)", ARG2, ARG3 );
+}
+
+POST(sys_pread7)
+{
+   vg_assert(SUCCESS);
+   POST_MEM_WRITE( ARG2, RES );
+}
+#endif
+
+PRE(sys_pwrite)
+{
+   Bool ok;
+   *flags |= SfMayBlock;
+   PRINT("sys_pwrite ( %ld, %#lx, %lu, %lu )", ARG1, ARG2, ARG3, ARG4);
+   PRE_REG_READ4(ssize_t, "pwrite",
+                 int, d, const void *, buf, vki_size_t, nbytes,
+                 vki_off_t, offset);
+   /* check to see if it is allowed.  If not, try for an exemption from
+      --sim-hints=enable-outer (used for self hosting). */
+   ok = ML_(fd_allowed)(ARG1, "pwrite", tid, False);
+   if (!ok && ARG1 == 2/*stderr*/
+           && SimHintiS(SimHint_enable_outer, VG_(clo_sim_hints)))
+      ok = True;
+   if (!ok)
+      SET_STATUS_Failure( VKI_EBADF );
+   else
+      PRE_MEM_READ( "pwrite(buf)", ARG2, ARG3 );
+}
+
+#if 0
+PRE(sys_pwrite7)
+{
+   Bool ok;
+   *flags |= SfMayBlock;
+   PRINT("sys_write ( %ld, %#lx, %lu, %lu )", ARG1, ARG2, ARG3, ARG4);
+   PRE_REG_READ4(ssize_t, "write",
+                 unsigned int, fd, const char *, buf, vki_size_t, count,
+                 unsigned long, off);
+   /* check to see if it is allowed.  If not, try for an exemption from
+      --sim-hints=enable-outer (used for self hosting). */
+   ok = ML_(fd_allowed)(ARG1, "write", tid, False);
+   if (!ok && ARG1 == 2/*stderr*/
+           && SimHintiS(SimHint_enable_outer, VG_(clo_sim_hints)))
+      ok = True;
+   if (!ok)
+      SET_STATUS_Failure( VKI_EBADF );
+   else
+      PRE_MEM_READ( "write(buf)", ARG2, ARG3 );
+}
+#endif
+
+PRE(sys_ftruncate)
+{
+   *flags |= SfMayBlock;
+   PRINT("sys_ftruncate ( %ld, %lu )", ARG1,ARG3);
+#if !defined(VGO_openbsd)
+   PRE_REG_READ3(long, "ftruncate", unsigned int, fd, int, pad,
+		  unsigned int, length);
+#else
+   PRE_REG_READ4(long, "ftruncate", long, sysno, unsigned int, fd, int, pad,
+		  unsigned int, length);
+#endif
+}
+
+#if 0
+PRE(sys_ftruncate7)
+{
+   *flags |= SfMayBlock;
+   PRINT("sys_ftruncate ( %ld, %lu )", ARG1,ARG2);
+   PRE_REG_READ2(long, "ftruncate", unsigned int, fd,
+		  unsigned long, length);
+}
+#endif
+
+PRE(sys_truncate)
+{
+   *flags |= SfMayBlock;
+   PRINT("sys_truncate ( %#lx(%s), %lu )", ARG1,(char *)ARG1,ARG3);
+#if !defined(VGO_openbsd)
+   PRE_REG_READ3(long, "truncate",
+                 const char *, path, int, pad, unsigned int, length);
+#else
+   PRE_REG_READ4(long, "truncate",
+                 long, sysno,
+                 const char *, path, int, pad, unsigned int, length);
+#endif
+   PRE_MEM_RASCIIZ( "truncate(path)", ARG1 );
+}
+
+#if 0
+PRE(sys_truncate7)
+{
+   *flags |= SfMayBlock;
+   PRINT("sys_truncate ( %#lx(%s), %lu )", ARG1,(char *)ARG1,ARG2);
+   PRE_REG_READ2(long, "truncate",
+                 const char *, path, unsigned long, length);
+   PRE_MEM_RASCIIZ( "truncate(path)", ARG1 );
+}
+#endif
+
+PRE(sys_sysarch)
+{
+   ThreadState *tst;
+   void **p;
+
+   PRINT("sys_sysarch ( %ld, %#lx )", ARG1, ARG2);
+   PRE_REG_READ2(int, "sysarch",
+                 int, number, void *, args);
+   switch (ARG1) {
+   case VKI_AMD64_SET_FSBASE:
+      PRINT("sys_amd64_set_fsbase ( %#lx )", ARG2);
+      PRE_REG_READ1(long, "amd64_set_fsbase", void *, base)
+
+      /* On FreeBSD, the syscall loads the %gs selector for us, so do it now. */
+      tst = VG_(get_ThreadState)(tid);
+      p = (void**)ARG2;
+      tst->arch.vex.guest_FS_CONST = (UWord)*p;
+      /* "do" the syscall ourselves; the kernel never sees it */
+      SET_STATUS_Success2((ULong)*p, tst->arch.vex.guest_RDX );
+
+      break;
+   case VKI_AMD64_GET_FSBASE:
+      PRINT("sys_amd64_get_fsbase ( %#lx )", ARG2);
+      PRE_REG_READ1(int, "amd64_get_fsbase", void *, basep)
+      PRE_MEM_WRITE( "amd64_get_fsbase(basep)", ARG2, sizeof(void *) );
+
+      /* "do" the syscall ourselves; the kernel never sees it */
+      tst = VG_(get_ThreadState)(tid);
+      SET_STATUS_Success2( tst->arch.vex.guest_FS_CONST, tst->arch.vex.guest_RDX );
+      POST_MEM_WRITE( ARG2, sizeof(void *) );
+      break;
+   default:
+      VG_(message) (Vg_UserMsg, "unhandled sysarch cmd %ld", ARG1);
+      VG_(unimplemented) ("unhandled sysarch cmd");
+      break;
+   }
+}
+
+#undef PRE
+#undef POST
+
+#endif /* defined(VGP_amd64_openbsd) */
+
+/*--------------------------------------------------------------------*/
+/*--- end                                                          ---*/
+/*--------------------------------------------------------------------*/
