Description: <short summary of the patch>
 TODO: Put a short summary on the line above and replace this paragraph
 with a longer explanation of this change. Complete the meta-information
 with other relevant fields (see below for details). To make it easier, the
 information below has been extracted from the changelog. Adjust it or drop
 it.
 .
 mono (3.2.3+dfsg-4) experimental; urgency=low
 .
   [ Alex Rønne Petersen ]
   * [17c6b02] Merge branch 'armhf' of github.com:alexrp/mono
     (cherry picked from commit b9bcafb382666ccf2f2848065f1760c8f322fa4d)
 .
   [ Jo Shields ]
   * [cf19c56] Add support for armhf packages
Author: Jo Shields <directhex@apebox.org>

---
The information above should follow the Patch Tagging Guidelines, please
checkout http://dep.debian.net/deps/dep3/ to learn about the format. Here
are templates for supplementary fields that you might want to add:

Origin: <vendor|upstream|other>, <url of original patch>
Bug: <url in upstream bugtracker>
Bug-Debian: http://bugs.debian.org/<bugnumber>
Bug-Ubuntu: https://launchpad.net/bugs/<bugnumber>
Forwarded: <no|not-needed|url proving that it has been forwarded>
Reviewed-By: <name and email of someone who approved the patch>
Last-Update: <YYYY-MM-DD>

--- mono-3.2.3+dfsg.orig/configure.in
+++ mono-3.2.3+dfsg/configure.in
@@ -143,6 +143,17 @@ case "$host" in
 		with_sigaltstack=no
 		use_sigposix=yes
 		;;
+	*-*-kfreebsd*-gnu)
+		platform_win32=no
+		CPPFLAGS="$CPPFLAGS -DGC_FREEBSD_THREADS -D_GNU_SOURCE -D_REENTRANT -DUSE_MMAP -DUSE_MUNMAP -DTHREAD_LOCAL_ALLOC -pthread"
+		libmono_cflags="-D_REENTRANT -DTHREAD_LOCAL_ALLOC -pthread"
+		libmono_ldflags="-lpthread -pthread"
+		libdl="-ldl"
+		libgc_threads=pthreads
+		need_link_unlink=yes
+		with_sigaltstack=no
+		use_sigposix=yes
+		;;
 	*-*-*freebsd*)
 		host_win32=no
 		if test "x$PTHREAD_CFLAGS" = "x"; then
@@ -2508,7 +2519,7 @@ case "$host" in
 			sgen_supported=true
 			AOT_SUPPORTED="yes"
 			;;
-		  darwin*|openbsd*|freebsd*)
+		  darwin*|openbsd*|freebsd*|kfreebsd-gnu*)
 			sgen_supported=true
 		        ;;
 		esac
@@ -2526,7 +2537,7 @@ case "$host" in
 			sgen_supported=true
 			AOT_SUPPORTED="yes"
 			;;
-		  darwin*|openbsd*|freebsd*)
+		  darwin*|openbsd*|freebsd*|kfreebsd-gnu*)
 			sgen_supported=true
 			;;
 		esac
@@ -2769,7 +2780,7 @@ esac
 dnl Use GCC atomic ops if they work on the target.
 if test x$GCC = "xyes"; then
 	case $TARGET in
-	X86 | AMD64 | ARM | POWERPC | POWERPC64 | MIPS)
+	X86 | AMD64 | ARM | POWERPC | POWERPC64 | MIPS | S390X)
 		AC_DEFINE(USE_GCC_ATOMIC_OPS, 1, [...])
 		;;
 	esac
@@ -2882,6 +2893,11 @@ case "$host" in
 	LIBC="libc.so.12"
 	INTL="libintl.so.0"
 	;;
+     *-*-kfreebsd*-gnu)
+	LIBC="libc.so.0.1"
+	INTL="libc.so.0.1"
+	X11="libX11.so.6"
+	;;
     *-*-*freebsd*)
     	LIBC="libc.so"
 	INTL="libintl.so"
@@ -3071,6 +3087,8 @@ if test ${TARGET} = ARM; then
 		return 0;
 	], [
 		arm_v5=yes
+
+		arm_ver=ARMv5
 	], [])
 
 	AC_TRY_COMPILE([], [
@@ -3081,6 +3099,8 @@ if test ${TARGET} = ARM; then
 	], [
 		arm_v5=yes
 		arm_v6=yes
+
+		arm_ver=ARMv6
 	], [])
 
 	AC_TRY_COMPILE([], [
@@ -3092,8 +3112,12 @@ if test ${TARGET} = ARM; then
 		arm_v5=yes
 		arm_v6=yes
 		arm_v7=yes
+
+		arm_ver=ARMv7
 	], [])
 
+	AC_MSG_RESULT($arm_ver)
+
 	if test x$arm_v5 = xyes; then
 		AC_DEFINE(HAVE_ARMV5, 1, [ARM v5])
 		CPPFLAGS_FOR_LIBGC="$CPPFLAGS_FOR_LIBGC -DHAVE_ARMV5=1"
--- mono-3.2.3+dfsg.orig/Makefile.am
+++ mono-3.2.3+dfsg/Makefile.am
@@ -3,7 +3,7 @@ ACLOCAL_AMFLAGS = -I m4
 MONOTOUCH_SUBDIRS = $(libgc_dir) eglib/src mono
 
 if CROSS_COMPILING
-SUBDIRS = po $(libgc_dir) eglib mono $(ikvm_native_dir) data runtime scripts man samples msvc $(docs_dir)
+SUBDIRS = po $(libgc_dir) eglib mono $(ikvm_native_dir) data runtime scripts man samples msvc
 # Keep in sync with SUBDIRS
 ## 'tools' is not normally built
 DIST_SUBDIRS = m4 po libgc eglib mono ikvm-native data runtime scripts man samples tools msvc docs
@@ -11,7 +11,7 @@ else
 if ONLY_MONOTOUCH
 SUBDIRS = $(MONOTOUCH_SUBDIRS) runtime
 else
-SUBDIRS = po $(libgc_dir) eglib mono $(ikvm_native_dir) support data runtime scripts man samples msvc $(docs_dir)
+SUBDIRS = po $(libgc_dir) eglib mono $(ikvm_native_dir) support data runtime scripts man samples msvc
 # Keep in sync with SUBDIRS
 ## 'tools' is not normally built
 DIST_SUBDIRS = m4 po libgc eglib mono ikvm-native support data runtime scripts man samples tools msvc docs
--- mono-3.2.3+dfsg.orig/mono/io-layer/io.c
+++ mono-3.2.3+dfsg/mono/io-layer/io.c
@@ -4227,7 +4227,7 @@ get_fstypename (gchar *utfpath)
 }
 
 /* Linux has struct statfs which has a different layout */
-#if defined (PLATFORM_MACOSX) || defined (__linux__) || defined(PLATFORM_BSD) || defined(__native_client__)
+#if defined (PLATFORM_MACOSX) || defined (__linux__) || defined(PLATFORM_BSD) || defined(__native_client__) || defined(__FreeBSD_kernel__)
 gboolean
 GetVolumeInformation (const gunichar2 *path, gunichar2 *volumename, int volumesize, int *outserial, int *maxcomp, int *fsflags, gunichar2 *fsbuffer, int fsbuffersize)
 {
--- mono-3.2.3+dfsg.orig/mono/mini/mini-arm.h
+++ mono-3.2.3+dfsg/mono/mini/mini-arm.h
@@ -19,10 +19,6 @@
 #define MONO_ARCH_SOFT_FLOAT_FALLBACK 1
 #endif
 
-#ifdef ARM_FPU_VFP_HARD
-#error "hardfp-abi not yet supported."
-#endif
-
 #if defined(__ARM_EABI__)
 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
 #define ARM_ARCHITECTURE "armel"
@@ -56,10 +52,9 @@
 #endif
 
 #define MONO_MAX_IREGS 16
-#define MONO_MAX_FREGS 16
+#define MONO_MAX_FREGS 32
 
 #define MONO_SAVED_GREGS 10 /* r4-r11, ip, lr */
-#define MONO_SAVED_FREGS 8
 
 /* r4-r11, ip, lr: registers saved in the LMF  */
 #define MONO_ARM_REGSAVE_MASK 0x5ff0
@@ -71,9 +66,32 @@
 #define MONO_ARCH_CALLEE_REGS ((1<<ARMREG_R0) | (1<<ARMREG_R1) | (1<<ARMREG_R2) | (1<<ARMREG_R3) | (1<<ARMREG_IP))
 #define MONO_ARCH_CALLEE_SAVED_REGS ((1<<ARMREG_V1) | (1<<ARMREG_V2) | (1<<ARMREG_V3) | (1<<ARMREG_V4) | (1<<ARMREG_V5) | (1<<ARMREG_V6) | (1<<ARMREG_V7))
 
-/* Every double precision vfp register, d0/d1 is reserved for a scratch reg */
-#define MONO_ARCH_CALLEE_FREGS 0x55555550
-#define MONO_ARCH_CALLEE_SAVED_FREGS 0
+/*
+ * TODO: Make use of VFP v3 registers d16-d31.
+ */
+
+/*
+ * TODO: We can't use registers d8-d15 in hard float mode because the
+ * register allocator doesn't allocate floating point registers globally.
+ */
+
+#if defined(ARM_FPU_VFP_HARD)
+#define MONO_SAVED_FREGS 16
+/*
+ * d8-d15 must be preserved across function calls. We use d14-d15 as
+ * scratch registers in the JIT. The rest have no meaning tied to them.
+ */
+#define MONO_ARCH_CALLEE_FREGS 0x00005555
+#define MONO_ARCH_CALLEE_SAVED_FREGS 0x55550000
+#else
+#define MONO_SAVED_FREGS 0
+/*
+ * No registers need to be preserved across function calls. We use d14-d15
+ * as scratch registers in the JIT. The rest have no meaning tied to them.
+ */
+#define MONO_ARCH_CALLEE_FREGS 0x05555555
+#define MONO_ARCH_CALLEE_SAVED_FREGS 0x00000000
+#endif
 
 #define MONO_ARCH_USE_FPSTACK FALSE
 #define MONO_ARCH_FPSTACK_SIZE 0
@@ -164,6 +182,10 @@ struct MonoLMF {
 	mgreg_t    sp;
 	mgreg_t    ip;
 	mgreg_t    fp;
+	/* Currently only used in trampolines on armhf to hold d0-d15. We don't really
+	 * need to put d0-d7 in the LMF, but it simplifies the trampoline code.
+	 */
+	double     fregs [16];
 	/* all but sp and pc: matches the PUSH instruction layout in the trampolines
 	 * 0-4 should be considered undefined (execpt in the magic tramp)
 	 * sp is saved at IP.
@@ -291,4 +313,7 @@ guint8*
 mono_arm_load_jumptable_entry (guint8 *code, gpointer *jte, ARMReg reg) MONO_INTERNAL;
 #endif
 
+gboolean
+mono_arm_is_hard_float (void) MONO_INTERNAL;
+
 #endif /* __MONO_MINI_ARM_H__ */
--- mono-3.2.3+dfsg.orig/mono/mini/Makefile.am
+++ mono-3.2.3+dfsg/mono/mini/Makefile.am
@@ -193,7 +193,7 @@ buildver-boehm.h: libmini-static.la $(mo
 else
 buildver-boehm.h: libmini-static.la $(monodir)/mono/metadata/libmonoruntime-static.la
 endif
-	@echo "const char *build_date = \"`date`\";" > buildver-boehm.h
+	@echo "const char *build_date;" > buildver-boehm.h
 mono_boehm-main.$(OBJEXT): buildver-boehm.h
 endif
 
@@ -202,7 +202,7 @@ buildver-sgen.h: libmini-static.la $(mon
 else
 buildver-sgen.h: libmini-static.la $(monodir)/mono/metadata/libmonoruntimesgen-static.la
 endif
-	@echo "const char *build_date = \"`date`\";" > buildver-sgen.h
+	@echo "const char *build_date;" > buildver-sgen.h
 mono_sgen-main-sgen.$(OBJEXT): buildver-sgen.h
 
 if DTRACE_G_REQUIRED
@@ -742,16 +742,7 @@ EXTRA_DIST = TestDriver.cs ldscript ldsc
 	Makefile.am.in
 
 version.h: Makefile
-	if test -d $(top_srcdir)/.git; then \
-		(cd $(top_srcdir); \
-			LANG=C; export LANG; \
-			branch=`git branch | grep '^\*' | cut -d ' ' -f 2`; \
-			version=`git log --no-color --first-parent -n1 --pretty=format:%h`; \
-			echo "#define FULL_VERSION \"$$branch/$$version\""; \
-		); \
-	else \
-		echo "#define FULL_VERSION \"tarball\""; \
-	fi > version.h
+	echo "#define FULL_VERSION \"Debian $$(dpkg-parsechangelog -l$(top_srcdir)/debian/changelog | grep ^Vers | cut -d\  -f2)\"" > version.h
 
 # Utility target for patching libtool to speed up linking
 patch-libtool:
--- mono-3.2.3+dfsg.orig/mono/mini/mini-amd64.h
+++ mono-3.2.3+dfsg/mono/mini/mini-amd64.h
@@ -290,7 +290,7 @@ typedef struct MonoCompileArch {
 
 #define MONO_ARCH_NOMAP32BIT
 
-#elif defined (__FreeBSD__)
+#elif defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
 
 #define REG_RAX 7
 #define REG_RCX 4
--- mono-3.2.3+dfsg.orig/mono/mini/mini.h
+++ mono-3.2.3+dfsg/mono/mini/mini.h
@@ -846,6 +846,10 @@ struct MonoCallInst {
 	LLVMCallInfo *cinfo;
 	int rgctx_arg_reg, imt_arg_reg;
 #endif
+#ifdef TARGET_ARM
+	/* See the comment in mini-arm.c!mono_arch_emit_call for RegTypeFP. */
+	GSList *float_args;
+#endif
 };
 
 struct MonoCallArgParm {
--- mono-3.2.3+dfsg.orig/mono/mini/mini.c
+++ mono-3.2.3+dfsg/mono/mini/mini.c
@@ -6766,7 +6766,6 @@ mini_create_ftnptr (MonoDomain *domain,
 	desc [0] = addr;
 	desc [1] = NULL;
 #	elif defined(__ppc64__) || defined(__powerpc64__)
-	gpointer *desc;
 
 	desc = mono_domain_alloc0 (domain, 3 * sizeof (gpointer));
 
--- mono-3.2.3+dfsg.orig/mono/mini/tramp-arm.c
+++ mono-3.2.3+dfsg/mono/mini/tramp-arm.c
@@ -16,6 +16,7 @@
 #include <mono/metadata/marshal.h>
 #include <mono/metadata/tabledefs.h>
 #include <mono/arch/arm/arm-codegen.h>
+#include <mono/arch/arm/arm-vfp-codegen.h>
 
 #include "mini.h"
 #include "mini-arm.h"
@@ -179,7 +180,7 @@ emit_bx (guint8* code, int reg)
 	return code;
 }
 
-/* Stack size for trampoline function 
+/* Stack size for trampoline function
  */
 #define STACK ALIGN_TO (sizeof (MonoLMF), 8)
 
@@ -201,7 +202,7 @@ mono_arch_create_generic_trampoline (Mon
 	gpointer *constants;
 #endif
 
-	int cfa_offset, lmf_offset, regsave_size, lr_offset;
+	int cfa_offset, regsave_size, lr_offset;
 	GSList *unwind_ops = NULL;
 	MonoJumpInfo *ji = NULL;
 	int buf_len;
@@ -213,7 +214,12 @@ mono_arch_create_generic_trampoline (Mon
 	/* Now we'll create in 'buf' the ARM trampoline code. This
 	 is the trampoline code common to all methods  */
 
-	buf_len = 212;
+	buf_len = 272;
+
+	/* Add space for saving/restoring VFP regs. */
+	if (mono_arm_is_hard_float ())
+		buf_len += 8 * 2;
+
 	code = buf = mono_global_codeman_reserve (buf_len);
 
 	/*
@@ -222,8 +228,6 @@ mono_arch_create_generic_trampoline (Mon
 	 * saved as sp + LR_OFFSET by the push in the specific trampoline
 	 */
 
-	/* The offset of lmf inside the stack frame */
-	lmf_offset = STACK - sizeof (MonoLMF);
 	/* The size of the area already allocated by the push in the specific trampoline */
 	regsave_size = 14 * sizeof (mgreg_t);
 	/* The offset where lr was saved inside the regsave area */
@@ -288,11 +292,13 @@ mono_arch_create_generic_trampoline (Mon
 	 * The pointer to the struct is put in r1.
 	 * the iregs array is already allocated on the stack by push.
 	 */
-	ARM_SUB_REG_IMM8 (code, ARMREG_SP, ARMREG_SP, STACK - regsave_size);
+	code = mono_arm_emit_load_imm (code, ARMREG_R2, STACK - regsave_size);
+	ARM_SUB_REG_REG (code, ARMREG_SP, ARMREG_SP, ARMREG_R2);
 	cfa_offset += STACK - regsave_size;
 	mono_add_unwind_op_def_cfa_offset (unwind_ops, code, buf, cfa_offset);
 	/* V1 == lmf */
-	ARM_ADD_REG_IMM8 (code, ARMREG_V1, ARMREG_SP, STACK - sizeof (MonoLMF));
+	code = mono_arm_emit_load_imm (code, ARMREG_R2, STACK - sizeof (MonoLMF));
+	ARM_ADD_REG_REG (code, ARMREG_V1, ARMREG_SP, ARMREG_R2);
 
 	/*
 	 * The stack now looks like:
@@ -316,7 +322,8 @@ mono_arch_create_generic_trampoline (Mon
 		ARM_STR_IMM (code, ARMREG_R2, ARMREG_V1, G_STRUCT_OFFSET (MonoLMF, method));
 	}
 	/* save caller SP */
-	ARM_ADD_REG_IMM8 (code, ARMREG_R2, ARMREG_SP, cfa_offset);
+	code = mono_arm_emit_load_imm (code, ARMREG_R2, cfa_offset);
+	ARM_ADD_REG_REG (code, ARMREG_R2, ARMREG_SP, ARMREG_R2);
 	ARM_STR_IMM (code, ARMREG_R2, ARMREG_V1, G_STRUCT_OFFSET (MonoLMF, sp));
 	/* save caller FP */
 	ARM_LDR_IMM (code, ARMREG_R2, ARMREG_V1, (G_STRUCT_OFFSET (MonoLMF, iregs) + ARMREG_FP*4));
@@ -329,11 +336,22 @@ mono_arch_create_generic_trampoline (Mon
 	}
 	ARM_STR_IMM (code, ARMREG_R2, ARMREG_V1, G_STRUCT_OFFSET (MonoLMF, ip));
 
+	/* Save VFP registers. */
+	if (mono_arm_is_hard_float ()) {
+		/*
+		 * Strictly speaking, we don't have to save d0-d7 in the LMF, but
+		 * it's easier than attempting to store them on the stack since
+		 * this trampoline code is pretty messy.
+		 */
+		ARM_ADD_REG_IMM8 (code, ARMREG_R0, ARMREG_V1, G_STRUCT_OFFSET (MonoLMF, fregs));
+		ARM_FSTMD (code, ARM_VFP_D0, 8, ARMREG_R0);
+	}
+
 	/*
 	 * Now we're ready to call xxx_trampoline ().
 	 */
 	/* Arg 1: the saved registers */
-	ARM_ADD_REG_IMM8 (code, ARMREG_R0, ARMREG_V1, G_STRUCT_OFFSET (MonoLMF, iregs));
+	ARM_ADD_REG_IMM (code, ARMREG_R0, ARMREG_V1, G_STRUCT_OFFSET (MonoLMF, iregs), 0);
 
 	/* Arg 2: code (next address to the instruction that called us) */
 	if (tramp_type == MONO_TRAMPOLINE_JUMP) {
@@ -413,6 +431,12 @@ mono_arch_create_generic_trampoline (Mon
 	/* *(lmf_addr) = previous_lmf */
 	ARM_STR_IMM (code, ARMREG_IP, ARMREG_LR, G_STRUCT_OFFSET (MonoLMF, previous_lmf));
 
+	/* Restore VFP registers. */
+	if (mono_arm_is_hard_float ()) {
+		ARM_ADD_REG_IMM8 (code, ARMREG_R0, ARMREG_V1, G_STRUCT_OFFSET (MonoLMF, fregs));
+		ARM_FLDMD (code, ARM_VFP_D0, 8, ARMREG_R0);
+	}
+
 	/* Non-standard function epilogue. Instead of doing a proper
 	 * return, we just jump to the compiled code.
 	 */
--- mono-3.2.3+dfsg.orig/mono/mini/mini-x86.h
+++ mono-3.2.3+dfsg/mono/mini/mini-x86.h
@@ -48,7 +48,7 @@ struct sigcontext {
 #endif /* __HAIKU__ */
 
 #if defined( __linux__) || defined(__sun) || defined(__APPLE__) || defined(__NetBSD__) || \
-       defined(__FreeBSD__) || defined(__OpenBSD__)
+       defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__)
 #define MONO_ARCH_USE_SIGACTION
 #endif
 
--- mono-3.2.3+dfsg.orig/mono/mini/mini-arm.c
+++ mono-3.2.3+dfsg/mono/mini/mini-arm.c
@@ -30,11 +30,26 @@
 #error "ARM_FPU_NONE is defined while one of ARM_FPU_VFP/ARM_FPU_VFP_HARD is defined"
 #endif
 
-#if defined(MONO_ARCH_SOFT_FLOAT_FALLBACK)
+/*
+ * IS_SOFT_FLOAT: Is full software floating point used?
+ * IS_HARD_FLOAT: Is full hardware floating point used?
+ * IS_VFP: Is hardware floating point with software ABI used?
+ *
+ * These are not necessarily constants, e.g. IS_SOFT_FLOAT and
+ * IS_VFP may delegate to mono_arch_is_soft_float ().
+ */
+
+#if defined(ARM_FPU_VFP_HARD)
+#define IS_SOFT_FLOAT (FALSE)
+#define IS_HARD_FLOAT (TRUE)
+#define IS_VFP (TRUE)
+#elif defined(ARM_FPU_NONE)
 #define IS_SOFT_FLOAT (mono_arch_is_soft_float ())
+#define IS_HARD_FLOAT (FALSE)
 #define IS_VFP (!mono_arch_is_soft_float ())
 #else
 #define IS_SOFT_FLOAT (FALSE)
+#define IS_HARD_FLOAT (FALSE)
 #define IS_VFP (TRUE)
 #endif
 
@@ -105,6 +120,9 @@ static gboolean iphone_abi = FALSE;
  */
 static MonoArmFPU arm_fpu;
 
+static int vfp_scratch1 = ARM_VFP_F28;
+static int vfp_scratch2 = ARM_VFP_F30;
+
 static int i8_align;
 
 static volatile int ss_trigger_var = 0;
@@ -354,7 +372,6 @@ mono_arm_load_jumptable_entry (guint8 *c
 }
 #endif
 
-
 static guint8*
 emit_move_return_value (MonoCompile *cfg, MonoInst *ins, guint8 *code)
 {
@@ -364,10 +381,18 @@ emit_move_return_value (MonoCompile *cfg
 	case OP_FCALL_MEMBASE:
 		if (IS_VFP) {
 			if (((MonoCallInst*)ins)->signature->ret->type == MONO_TYPE_R4) {
-				ARM_FMSR (code, ins->dreg, ARMREG_R0);
-				ARM_CVTS (code, ins->dreg, ins->dreg);
+				if (IS_HARD_FLOAT) {
+					ARM_CVTS (code, ins->dreg, ARM_VFP_F0);
+				} else {
+					ARM_FMSR (code, ins->dreg, ARMREG_R0);
+					ARM_CVTS (code, ins->dreg, ins->dreg);
+				}
 			} else {
-				ARM_FMDRR (code, ARMREG_R0, ARMREG_R1, ins->dreg);
+				if (IS_HARD_FLOAT) {
+					ARM_CPYD (code, ins->dreg, ARM_VFP_D0);
+				} else {
+					ARM_FMDRR (code, ARMREG_R0, ARMREG_R1, ins->dreg);
+				}
 			}
 		}
 		break;
@@ -465,6 +490,37 @@ emit_save_lmf (MonoCompile *cfg, guint8
 	return code;
 }
 
+typedef struct {
+	gint32 vreg;
+	gint32 hreg;
+} FloatArgData;
+
+static guint8 *
+emit_float_args (MonoCompile *cfg, MonoCallInst *inst, guint8 *code, int *max_len, guint *offset)
+{
+	GSList *list;
+
+	for (list = inst->float_args; list; list = list->next) {
+		FloatArgData *fad = list->data;
+		MonoInst *var = get_vreg_to_inst (cfg, fad->vreg);
+
+		*max_len += 4;
+
+		if (*offset + *max_len > cfg->code_size) {
+			cfg->code_size += *max_len;
+			cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
+
+			code = cfg->native_code + *offset;
+		}
+
+		ARM_FLDS (code, fad->hreg, var->inst_basereg, var->inst_offset);
+
+		*offset = code - cfg->native_code;
+	}
+
+	return code;
+}
+
 /*
  * emit_save_lmf:
  *
@@ -904,6 +960,12 @@ mono_arch_is_soft_float (void)
 }
 #endif
 
+gboolean
+mono_arm_is_hard_float (void)
+{
+	return arm_fpu == MONO_ARM_FPU_VFP_HARD;
+}
+
 static gboolean
 is_regsize_var (MonoGenericSharingContext *gsctx, MonoType *t) {
 	if (t->byref)
@@ -1152,10 +1214,97 @@ add_general (guint *gr, guint *stack_siz
 	(*gr) ++;
 }
 
+static void inline
+add_float (guint *fpr, guint *stack_size, ArgInfo *ainfo, gboolean is_double, gint *float_spare)
+{
+	/*
+	 * If we're calling a function like this:
+	 *
+	 * void foo(float a, double b, float c)
+	 *
+	 * We pass a in s0 and b in d1. That leaves us
+	 * with s1 being unused. The armhf ABI recognizes
+	 * this and requires register assignment to then
+	 * use that for the next single-precision arg,
+	 * i.e. c in this example. So float_spare either
+	 * tells us which reg to use for the next single-
+	 * precision arg, or it's -1, meaning use *fpr.
+	 *
+	 * Note that even though most of the JIT speaks
+	 * double-precision, fpr represents single-
+	 * precision registers.
+	 *
+	 * See parts 5.5 and 6.1.2 of the AAPCS for how
+	 * this all works.
+	 */
+
+	if (*fpr < ARM_VFP_F16 || (!is_double && *float_spare >= 0)) {
+		ainfo->storage = RegTypeFP;
+
+		if (is_double) {
+			/*
+			 * If we're passing a double-precision value
+			 * and *fpr is odd (e.g. it's s1, s3, ...)
+			 * we need to use the next even register. So
+			 * we mark the current *fpr as a spare that
+			 * can be used for the next single-precision
+			 * value.
+			 */
+			if (*fpr % 2) {
+				*float_spare = *fpr;
+				(*fpr)++;
+			}
+
+			/*
+			 * At this point, we have an even register
+			 * so we assign that and move along.
+			 */
+			ainfo->reg = *fpr;
+			*fpr += 2;
+		} else if (*float_spare >= 0) {
+			/*
+			 * We're passing a single-precision value
+			 * and it looks like a spare single-
+			 * precision register is available. Let's
+			 * use it.
+			 */
+
+			ainfo->reg = *float_spare;
+			*float_spare = -1;
+		} else {
+			/*
+			 * If we hit this branch, we're passing a
+			 * single-precision value and we can simply
+			 * use the next available register.
+			 */
+
+			ainfo->reg = *fpr;
+			(*fpr)++;
+		}
+	} else {
+		/*
+		 * We've exhausted available floating point
+		 * regs, so pass the rest on the stack.
+		 */
+
+		if (is_double) {
+			*stack_size += 7;
+			*stack_size &= ~7;
+		}
+
+		ainfo->offset = *stack_size;
+		ainfo->reg = ARMREG_SP;
+		ainfo->storage = RegTypeBase;
+
+		*stack_size += 8;
+	}
+}
+
 static CallInfo*
 get_call_info (MonoGenericSharingContext *gsctx, MonoMemPool *mp, MonoMethodSignature *sig)
 {
-	guint i, gr, pstart;
+	guint i, gr, fpr, pstart;
+	gint float_spare;
 	int n = sig->hasthis + sig->param_count;
 	MonoType *simpletype;
 	guint32 stack_size = 0;
@@ -1170,6 +1319,8 @@ get_call_info (MonoGenericSharingContext
 
 	cinfo->nargs = n;
 	gr = ARMREG_R0;
+	fpr = ARM_VFP_F0;
+	float_spare = -1;
 
 	t = mini_type_get_underlying_type (gsctx, sig->ret);
 	if (MONO_TYPE_ISSTRUCT (t)) {
@@ -1222,6 +1373,7 @@ get_call_info (MonoGenericSharingContext
 			/* Prevent implicit arguments and sig_cookie from
 			   being passed in registers */
 			gr = ARMREG_R3 + 1;
+			fpr = ARM_VFP_F16;
 			/* Emit the signature cookie just before the implicit arguments */
 			add_general (&gr, &stack_size, &cinfo->sig_cookie, TRUE);
 		}
@@ -1263,7 +1415,6 @@ get_call_info (MonoGenericSharingContext
 		case MONO_TYPE_STRING:
 		case MONO_TYPE_SZARRAY:
 		case MONO_TYPE_ARRAY:
-		case MONO_TYPE_R4:
 			cinfo->args [n].size = sizeof (gpointer);
 			add_general (&gr, &stack_size, ainfo, TRUE);
 			n++;
@@ -1344,11 +1495,30 @@ get_call_info (MonoGenericSharingContext
 		}
 		case MONO_TYPE_U8:
 		case MONO_TYPE_I8:
-		case MONO_TYPE_R8:
 			ainfo->size = 8;
 			add_general (&gr, &stack_size, ainfo, FALSE);
 			n++;
 			break;
+		case MONO_TYPE_R4:
+			ainfo->size = 4;
+
+			if (IS_HARD_FLOAT)
+				add_float (&fpr, &stack_size, ainfo, FALSE, &float_spare);
+			else
+				add_general (&gr, &stack_size, ainfo, TRUE);
+
+			n++;
+			break;
+		case MONO_TYPE_R8:
+			ainfo->size = 8;
+
+			if (IS_HARD_FLOAT)
+				add_float (&fpr, &stack_size, ainfo, TRUE, &float_spare);
+			else
+				add_general (&gr, &stack_size, ainfo, FALSE);
+
+			n++;
+			break;
 		case MONO_TYPE_VAR:
 		case MONO_TYPE_MVAR:
 			/* gsharedvt arguments are passed by ref */
@@ -1376,6 +1546,7 @@ get_call_info (MonoGenericSharingContext
 		/* Prevent implicit arguments and sig_cookie from
 		   being passed in registers */
 		gr = ARMREG_R3 + 1;
+		fpr = ARM_VFP_F16;
 		/* Emit the signature cookie just before the implicit arguments */
 		add_general (&gr, &stack_size, &cinfo->sig_cookie, TRUE);
 	}
@@ -1411,9 +1582,13 @@ get_call_info (MonoGenericSharingContext
 		case MONO_TYPE_R4:
 		case MONO_TYPE_R8:
 			cinfo->ret.storage = RegTypeFP;
-			cinfo->ret.reg = ARMREG_R0;
-			/* FIXME: cinfo->ret.reg = ???;
-			cinfo->ret.storage = RegTypeFP;*/
+
+			if (IS_HARD_FLOAT) {
+				cinfo->ret.reg = ARM_VFP_F0;
+			} else {
+				cinfo->ret.reg = ARMREG_R0;
+			}
+
 			break;
 		case MONO_TYPE_GENERICINST:
 			if (!mono_type_generic_inst_is_valuetype (simpletype)) {
@@ -2104,19 +2279,50 @@ mono_arch_emit_call (MonoCompile *cfg, M
 			}
 			break;
 		case RegTypeFP: {
-			/* FIXME: */
-			NOT_IMPLEMENTED;
-#if 0
-			arg->backend.reg3 = ainfo->reg;
-			/* FP args are passed in int regs */
-			call->used_iregs |= 1 << ainfo->reg;
+			int fdreg = mono_alloc_freg (cfg);
+
 			if (ainfo->size == 8) {
-				arg->opcode = OP_OUTARG_R8;
-				call->used_iregs |= 1 << (ainfo->reg + 1);
+				MONO_INST_NEW (cfg, ins, OP_FMOVE);
+				ins->sreg1 = in->dreg;
+				ins->dreg = fdreg;
+				MONO_ADD_INS (cfg->cbb, ins);
+
+				mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, ainfo->reg, TRUE);
 			} else {
-				arg->opcode = OP_OUTARG_R4;
+				FloatArgData *fad;
+
+				/*
+				 * Mono's register allocator doesn't speak single-precision registers that
+				 * overlap double-precision registers (i.e. armhf). So we have to work around
+				 * the register allocator and load the value from memory manually.
+				 *
+				 * So we create a variable for the float argument and an instruction to store
+				 * the argument into the variable. We then store the list of these arguments
+				 * in cfg->float_args. This list is then used by emit_float_args later to
+				 * pass the arguments in the various call opcodes.
+				 *
+				 * This is not very nice, and we should really try to fix the allocator.
+				 */
+
+				MonoInst *float_arg = mono_compile_create_var (cfg, &mono_defaults.single_class->byval_arg, OP_LOCAL);
+
+				/* Make sure the instruction isn't seen as pointless and removed.
+				 */
+				float_arg->flags |= MONO_INST_VOLATILE;
+
+				MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, float_arg->dreg, in->dreg);
+
+				/* We use the dreg to look up the instruction later. The hreg is used to
+				 * emit the instruction that loads the value into the FP reg.
+				 */
+				fad = mono_mempool_alloc0 (cfg->mempool, sizeof (FloatArgData));
+				fad->vreg = float_arg->dreg;
+				fad->hreg = ainfo->reg;
+
+				call->float_args = g_slist_append_mempool (cfg->mempool, call->float_args, fad);
 			}
-#endif
+
+			call->used_iregs |= 1 << ainfo->reg;
 			cfg->flags |= MONO_CFG_HAS_FPOUT;
 			break;
 		}
@@ -2238,6 +2444,7 @@ mono_arch_emit_setret (MonoCompile *cfg,
 			}
 			break;
 		case MONO_ARM_FPU_VFP:
+		case MONO_ARM_FPU_VFP_HARD:
 			if (ret->type == MONO_TYPE_R8 || ret->type == MONO_TYPE_R4) {
 				MonoInst *ins;
 
@@ -3209,10 +3416,10 @@ emit_float_to_int (MonoCompile *cfg, guc
 	/* sreg is a float, dreg is an integer reg  */
 	if (IS_VFP) {
 		if (is_signed)
-			ARM_TOSIZD (code, ARM_VFP_F0, sreg);
+			ARM_TOSIZD (code, vfp_scratch1, sreg);
 		else
-			ARM_TOUIZD (code, ARM_VFP_F0, sreg);
-		ARM_FMRS (code, dreg, ARM_VFP_F0);
+			ARM_TOUIZD (code, vfp_scratch1, sreg);
+		ARM_FMRS (code, dreg, vfp_scratch1);
 	}
 	if (!is_signed) {
 		if (size == 1)
@@ -4364,6 +4571,10 @@ mono_arch_output_basic_block (MonoCompil
 		case OP_VOIDCALL:
 		case OP_CALL:
 			call = (MonoCallInst*)ins;
+
+			if (IS_HARD_FLOAT)
+				code = emit_float_args (cfg, call, code, &max_len, &offset);
+
 			if (ins->flags & MONO_INST_HAS_METHOD)
 				mono_add_patch_info (cfg, offset, MONO_PATCH_INFO_METHOD, call->method);
 			else
@@ -4379,6 +4590,9 @@ mono_arch_output_basic_block (MonoCompil
 		case OP_VCALL2_REG:
 		case OP_VOIDCALL_REG:
 		case OP_CALL_REG:
+			if (IS_HARD_FLOAT)
+				code = emit_float_args (cfg, (MonoCallInst *)ins, code, &max_len, &offset);
+
 			code = emit_call_reg (code, ins->sreg1);
 			ins->flags |= MONO_INST_GC_CALLSITE;
 			ins->backend.pc_offset = code - cfg->native_code;
@@ -4394,6 +4608,10 @@ mono_arch_output_basic_block (MonoCompil
 
 			g_assert (ins->sreg1 != ARMREG_LR);
 			call = (MonoCallInst*)ins;
+
+			if (IS_HARD_FLOAT)
+				code = emit_float_args (cfg, call, code, &max_len, &offset);
+
 			if (call->dynamic_imt_arg || call->method->klass->flags & TYPE_ATTRIBUTE_INTERFACE)
 				imt_arg = TRUE;
 			if (!arm_is_imm12 (ins->inst_offset))
@@ -4770,34 +4988,41 @@ mono_arch_output_basic_block (MonoCompil
 			break;
 		case OP_STORER4_MEMBASE_REG:
 			g_assert (arm_is_fpimm8 (ins->inst_offset));
-			ARM_CVTD (code, ARM_VFP_F0, ins->sreg1);
-			ARM_FSTS (code, ARM_VFP_F0, ins->inst_destbasereg, ins->inst_offset);
+			ARM_CVTD (code, vfp_scratch1, ins->sreg1);
+			ARM_FSTS (code, vfp_scratch1, ins->inst_destbasereg, ins->inst_offset);
 			break;
 		case OP_LOADR4_MEMBASE:
 			g_assert (arm_is_fpimm8 (ins->inst_offset));
-			ARM_FLDS (code, ARM_VFP_F0, ins->inst_basereg, ins->inst_offset);
-			ARM_CVTS (code, ins->dreg, ARM_VFP_F0);
+			ARM_FLDS (code, vfp_scratch1, ins->inst_basereg, ins->inst_offset);
+			ARM_CVTS (code, ins->dreg, vfp_scratch1);
 			break;
 		case OP_ICONV_TO_R_UN: {
 			g_assert_not_reached ();
 			break;
 		}
 		case OP_ICONV_TO_R4:
-			ARM_FMSR (code, ARM_VFP_F0, ins->sreg1);
-			ARM_FSITOS (code, ARM_VFP_F0, ARM_VFP_F0);
-			ARM_CVTS (code, ins->dreg, ARM_VFP_F0);
+			ARM_FMSR (code, vfp_scratch1, ins->sreg1);
+			ARM_FSITOS (code, vfp_scratch1, vfp_scratch1);
+			ARM_CVTS (code, ins->dreg, vfp_scratch1);
 			break;
 		case OP_ICONV_TO_R8:
-			ARM_FMSR (code, ARM_VFP_F0, ins->sreg1);
-			ARM_FSITOD (code, ins->dreg, ARM_VFP_F0);
+			ARM_FMSR (code, vfp_scratch1, ins->sreg1);
+			ARM_FSITOD (code, ins->dreg, vfp_scratch1);
 			break;
 
 		case OP_SETFRET:
 			if (mono_method_signature (cfg->method)->ret->type == MONO_TYPE_R4) {
 				ARM_CVTD (code, ARM_VFP_F0, ins->sreg1);
-				ARM_FMRS (code, ARMREG_R0, ARM_VFP_F0);
+
+				if (!IS_HARD_FLOAT) {
+					ARM_FMRS (code, ARMREG_R0, ARM_VFP_F0);
+				}
 			} else {
-				ARM_FMRRD (code, ARMREG_R0, ARMREG_R1, ins->sreg1);
+				if (IS_HARD_FLOAT) {
+					ARM_CPYD (code, ARM_VFP_D0, ins->sreg1);
+				} else {
+					ARM_FMRRD (code, ARMREG_R0, ARMREG_R1, ins->sreg1);
+				}
 			}
 			break;
 		case OP_FCONV_TO_I1:
@@ -4975,18 +5200,18 @@ mono_arch_output_basic_block (MonoCompil
 					jte [0] = GUINT_TO_POINTER (0xffffffff);
 					jte [1] = GUINT_TO_POINTER (0x7fefffff);
 					code = mono_arm_load_jumptable_entry_addr (code, jte, ARMREG_IP);
-					ARM_FLDD (code, ARM_VFP_D0, ARMREG_IP, 0);
+					ARM_FLDD (code, vfp_scratch1, ARMREG_IP, 0);
 				}
 #else
-				ARM_ABSD (code, ARM_VFP_D1, ins->sreg1);
-				ARM_FLDD (code, ARM_VFP_D0, ARMREG_PC, 0);
+				ARM_ABSD (code, vfp_scratch2, ins->sreg1);
+				ARM_FLDD (code, vfp_scratch1, ARMREG_PC, 0);
 				ARM_B (code, 1);
 				*(guint32*)code = 0xffffffff;
 				code += 4;
 				*(guint32*)code = 0x7fefffff;
 				code += 4;
 #endif
-				ARM_CMPD (code, ARM_VFP_D1, ARM_VFP_D0);
+				ARM_CMPD (code, vfp_scratch2, vfp_scratch1);
 				ARM_FMSTAT (code);
 				EMIT_COND_SYSTEM_EXCEPTION_FLAGS (ARMCOND_GT, "ArithmeticException");
 				ARM_CMPD (code, ins->sreg1, ins->sreg1);
@@ -5456,7 +5681,13 @@ mono_arch_emit_prolog (MonoCompile *cfg)
 					break;
 				}
 			} else if (ainfo->storage == RegTypeFP) {
-				g_assert_not_reached ();
+				code = mono_arm_emit_load_imm (code, ARMREG_IP, inst->inst_offset);
+				ARM_ADD_REG_REG (code, ARMREG_IP, ARMREG_IP, inst->inst_basereg);
+
+				if (ainfo->size == 8)
+					ARM_FSTD (code, ainfo->reg, ARMREG_IP, 0);
+				else
+					ARM_FSTS (code, ainfo->reg, ARMREG_IP, 0);
 			} else if (ainfo->storage == RegTypeStructByVal) {
 				int doffset = inst->inst_offset;
 				int soffset = 0;
--- mono-3.2.3+dfsg.orig/mono/mini/exceptions-arm.c
+++ mono-3.2.3+dfsg/mono/mini/exceptions-arm.c
@@ -60,10 +60,10 @@ mono_arch_get_restore_context (MonoTramp
 
 	ctx_reg = ARMREG_R0;
 
-#if defined(ARM_FPU_VFP)
-	ARM_ADD_REG_IMM8 (code, ARMREG_IP, ctx_reg, G_STRUCT_OFFSET (MonoContext, fregs));
-	ARM_FLDMD (code, ARM_VFP_D0, 16, ARMREG_IP);
-#endif
+	if (!mono_arch_is_soft_float ()) {
+		ARM_ADD_REG_IMM8 (code, ARMREG_IP, ctx_reg, G_STRUCT_OFFSET (MonoContext, fregs));
+		ARM_FLDMD (code, ARM_VFP_D0, 16, ARMREG_IP);
+	}
 
 	/* move pc to PC */
 	ARM_LDR_IMM (code, ARMREG_IP, ctx_reg, G_STRUCT_OFFSET (MonoContext, pc));
@@ -220,12 +220,12 @@ get_throw_trampoline (int size, gboolean
 	mono_add_unwind_op_offset (unwind_ops, code, start, ARMREG_LR, - sizeof (mgreg_t));
 
 	/* Save fp regs */
-	ARM_SUB_REG_IMM8 (code, ARMREG_SP, ARMREG_SP, sizeof (double) * 16);
-	cfa_offset += sizeof (double) * 16;
-	mono_add_unwind_op_def_cfa_offset (unwind_ops, code, start, cfa_offset);
-#if defined(ARM_FPU_VFP)
-	ARM_FSTMD (code, ARM_VFP_D0, 16, ARMREG_SP);
-#endif
+	if (!mono_arch_is_soft_float ()) {
+		ARM_SUB_REG_IMM8 (code, ARMREG_SP, ARMREG_SP, sizeof (double) * 16);
+		cfa_offset += sizeof (double) * 16;
+		mono_add_unwind_op_def_cfa_offset (unwind_ops, code, start, cfa_offset);
+		ARM_FSTMD (code, ARM_VFP_D0, 16, ARMREG_SP);
+	}
 
 	/* Param area */
 	ARM_SUB_REG_IMM8 (code, ARMREG_SP, ARMREG_SP, 8);
--- mono-3.2.3+dfsg.orig/mono/metadata/sgen-os-posix.c
+++ mono-3.2.3+dfsg/mono/metadata/sgen-os-posix.c
@@ -35,7 +35,7 @@
 #include "metadata/sgen-archdep.h"
 #include "metadata/object-internals.h"
 
-#if defined(__APPLE__) || defined(__OpenBSD__) || defined(__FreeBSD__)
+#if defined(__APPLE__) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
 const static int suspend_signal_num = SIGXFSZ;
 #else
 const static int suspend_signal_num = SIGPWR;
--- mono-3.2.3+dfsg.orig/mono/metadata/boehm-gc.c
+++ mono-3.2.3+dfsg/mono/metadata/boehm-gc.c
@@ -22,6 +22,7 @@
 #include <mono/metadata/marshal.h>
 #include <mono/metadata/runtime.h>
 #include <mono/utils/mono-logger-internal.h>
+#include <mono/utils/mono-memory-model.h>
 #include <mono/utils/mono-time.h>
 #include <mono/utils/mono-threads.h>
 #include <mono/utils/dtrace.h>
@@ -624,6 +625,12 @@ mono_gc_wbarrier_generic_store (gpointer
 }
 
 void
+mono_gc_wbarrier_generic_store_atomic (gpointer ptr, MonoObject *value)
+{
+	mono_atomic_store_release ((volatile MonoObject **) ptr, value);
+}
+
+void
 mono_gc_wbarrier_generic_nostore (gpointer ptr)
 {
 }
--- mono-3.2.3+dfsg.orig/mono/metadata/object.h
+++ mono-3.2.3+dfsg/mono/metadata/object.h
@@ -316,6 +316,7 @@ MONO_API void mono_gc_wbarrier_set_field
 MONO_API void mono_gc_wbarrier_set_arrayref  (MonoArray *arr, void* slot_ptr, MonoObject* value);
 MONO_API void mono_gc_wbarrier_arrayref_copy (void* dest_ptr, void* src_ptr, int count);
 MONO_API void mono_gc_wbarrier_generic_store (void* ptr, MonoObject* value);
+MONO_API void mono_gc_wbarrier_generic_store_atomic (void *ptr, MonoObject *value);
 MONO_API void mono_gc_wbarrier_generic_nostore (void* ptr);
 MONO_API void mono_gc_wbarrier_value_copy    (void* dest, void* src, int count, MonoClass *klass);
 MONO_API void mono_gc_wbarrier_object_copy   (MonoObject* obj, MonoObject *src);
--- mono-3.2.3+dfsg.orig/mono/metadata/security.c
+++ mono-3.2.3+dfsg/mono/metadata/security.c
@@ -13,6 +13,7 @@
 
 #include <mono/metadata/assembly.h>
 #include <mono/metadata/appdomain.h>
+#include <mono/metadata/assembly.h>
 #include <mono/metadata/image.h>
 #include <mono/metadata/exception.h>
 #include <mono/metadata/object-internals.h>
--- mono-3.2.3+dfsg.orig/mono/metadata/sgen-descriptor.h
+++ mono-3.2.3+dfsg/mono/metadata/sgen-descriptor.h
@@ -170,21 +170,43 @@ sgen_gc_descr_has_references (mword desc
 		}	\
 	} while (0)
 
-#ifdef __GNUC__
+#if defined(__GNUC__) && SIZEOF_VOID_P==4
 #define OBJ_BITMAP_FOREACH_PTR(desc,obj)       do {    \
 		/* there are pointers */        \
 		void **_objptr = (void**)(obj); \
 		gsize _bmap = (desc) >> 16;     \
 		_objptr += OBJECT_HEADER_WORDS; \
 		{ \
-			int _index = __builtin_ctz (_bmap); \
+			int _index = __builtin_ctz (_bmap);		\
 			_objptr += _index; \
 			_bmap >>= (_index + 1);				\
 			HANDLE_PTR (_objptr, (obj));		\
 			_objptr ++;							\
 			} \
 		while (_bmap) { \
-			int _index = __builtin_ctz (_bmap); \
+			int _index = __builtin_ctz (_bmap);		\
+			_objptr += _index; \
+			_bmap >>= (_index + 1);				\
+			HANDLE_PTR (_objptr, (obj));		\
+			_objptr ++;							\
+		}										\
+	} while (0)
+#elif defined(__GNUC__) && SIZEOF_VOID_P==8
+/* Same as above, but use _builtin_ctzl () */
+#define OBJ_BITMAP_FOREACH_PTR(desc,obj)       do {    \
+		/* there are pointers */        \
+		void **_objptr = (void**)(obj); \
+		gsize _bmap = (desc) >> 16;     \
+		_objptr += OBJECT_HEADER_WORDS; \
+		{ \
+			int _index = __builtin_ctzl (_bmap);		\
+			_objptr += _index; \
+			_bmap >>= (_index + 1);				\
+			HANDLE_PTR (_objptr, (obj));		\
+			_objptr ++;							\
+			} \
+		while (_bmap) { \
+			int _index = __builtin_ctzl (_bmap);		\
 			_objptr += _index; \
 			_bmap >>= (_index + 1);				\
 			HANDLE_PTR (_objptr, (obj));		\
--- mono-3.2.3+dfsg.orig/mono/metadata/null-gc.c
+++ mono-3.2.3+dfsg/mono/metadata/null-gc.c
@@ -193,6 +193,12 @@ mono_gc_wbarrier_generic_store (gpointer
 }
 
 void
+mono_gc_wbarrier_generic_store_atomic (gpointer ptr, MonoObject *value)
+{
+	mono_atomic_store_release ((volatile MonoObject **) ptr, value);
+}
+
+void
 mono_gc_wbarrier_generic_nostore (gpointer ptr)
 {
 }
--- mono-3.2.3+dfsg.orig/mono/metadata/sgen-gc.c
+++ mono-3.2.3+dfsg/mono/metadata/sgen-gc.c
@@ -317,6 +317,7 @@ static int stat_wbarrier_set_field = 0;
 static int stat_wbarrier_set_arrayref = 0;
 static int stat_wbarrier_arrayref_copy = 0;
 static int stat_wbarrier_generic_store = 0;
+static int stat_wbarrier_generic_store_atomic = 0;
 static int stat_wbarrier_set_root = 0;
 static int stat_wbarrier_value_copy = 0;
 static int stat_wbarrier_object_copy = 0;
@@ -2217,6 +2218,7 @@ init_stats (void)
 	mono_counters_register ("WBarrier set arrayref", MONO_COUNTER_GC | MONO_COUNTER_INT, &stat_wbarrier_set_arrayref);
 	mono_counters_register ("WBarrier arrayref copy", MONO_COUNTER_GC | MONO_COUNTER_INT, &stat_wbarrier_arrayref_copy);
 	mono_counters_register ("WBarrier generic store called", MONO_COUNTER_GC | MONO_COUNTER_INT, &stat_wbarrier_generic_store);
+	mono_counters_register ("WBarrier generic atomic store called", MONO_COUNTER_GC | MONO_COUNTER_INT, &stat_wbarrier_generic_store_atomic);
 	mono_counters_register ("WBarrier set root", MONO_COUNTER_GC | MONO_COUNTER_INT, &stat_wbarrier_set_root);
 	mono_counters_register ("WBarrier value copy", MONO_COUNTER_GC | MONO_COUNTER_INT, &stat_wbarrier_value_copy);
 	mono_counters_register ("WBarrier object copy", MONO_COUNTER_GC | MONO_COUNTER_INT, &stat_wbarrier_object_copy);
@@ -4424,6 +4426,24 @@ mono_gc_wbarrier_generic_store (gpointer
 	sgen_dummy_use (value);
 }
 
+/* Same as mono_gc_wbarrier_generic_store () but performs the store
+ * as an atomic operation with release semantics.
+ */
+void
+mono_gc_wbarrier_generic_store_atomic (gpointer ptr, MonoObject *value)
+{
+	HEAVY_STAT (++stat_wbarrier_generic_store_atomic);
+
+	SGEN_LOG (8, "Wbarrier atomic store at %p to %p (%s)", ptr, value, value ? safe_name (value) : "null");
+
+	mono_atomic_store_release ((volatile MonoObject **) ptr, value);
+
+	if (ptr_in_nursery (value))
+		mono_gc_wbarrier_generic_nostore (ptr);
+
+	sgen_dummy_use (value);
+}
+
 void mono_gc_wbarrier_value_copy_bitmap (gpointer _dest, gpointer _src, int size, unsigned bitmap)
 {
 	mword *dest = _dest;
--- mono-3.2.3+dfsg.orig/mono/metadata/threads.c
+++ mono-3.2.3+dfsg/mono/metadata/threads.c
@@ -48,6 +48,7 @@
 #include <mono/utils/hazard-pointer.h>
 #include <mono/utils/mono-tls.h>
 #include <mono/utils/atomic.h>
+#include <mono/utils/mono-memory-model.h>
 
 #include <mono/metadata/gc-internal.h>
 
@@ -1182,8 +1183,6 @@ HANDLE ves_icall_System_Threading_Thread
 
 void ves_icall_System_Threading_InternalThread_Thread_free_internal (MonoInternalThread *this, HANDLE thread)
 {
-	MONO_ARCH_SAVE_REGS;
-
 	THREAD_DEBUG (g_message ("%s: Closing thread %p, handle %p", __func__, this, thread));
 
 	if (thread)
@@ -1273,8 +1272,6 @@ void ves_icall_System_Threading_Thread_S
 gint32
 ves_icall_System_Threading_Thread_GetDomainID (void) 
 {
-	MONO_ARCH_SAVE_REGS;
-
 	return mono_domain_get()->domain_id;
 }
 
@@ -1640,8 +1637,6 @@ ves_icall_System_Threading_WaitHandle_Si
 	guint32 ret;
 	MonoInternalThread *thread = mono_thread_internal_current ();
 
-	MONO_ARCH_SAVE_REGS;
-
 	if (ms == -1)
 		ms = INFINITE;
 
@@ -1660,8 +1655,6 @@ HANDLE ves_icall_System_Threading_Mutex_
 { 
 	HANDLE mutex;
 	
-	MONO_ARCH_SAVE_REGS;
-   
 	*created = TRUE;
 	
 	if (name == NULL) {
@@ -1678,8 +1671,6 @@ HANDLE ves_icall_System_Threading_Mutex_
 }                                                                   
 
 MonoBoolean ves_icall_System_Threading_Mutex_ReleaseMutex_internal (HANDLE handle ) { 
-	MONO_ARCH_SAVE_REGS;
-
 	return(ReleaseMutex (handle));
 }
 
@@ -1689,8 +1680,6 @@ HANDLE ves_icall_System_Threading_Mutex_
 {
 	HANDLE ret;
 	
-	MONO_ARCH_SAVE_REGS;
-	
 	*error = ERROR_SUCCESS;
 	
 	ret = OpenMutex (rights, FALSE, mono_string_chars (name));
@@ -1706,8 +1695,6 @@ HANDLE ves_icall_System_Threading_Semaph
 { 
 	HANDLE sem;
 	
-	MONO_ARCH_SAVE_REGS;
-   
 	*created = TRUE;
 	
 	if (name == NULL) {
@@ -1728,8 +1715,6 @@ gint32 ves_icall_System_Threading_Semaph
 { 
 	gint32 prevcount;
 	
-	MONO_ARCH_SAVE_REGS;
-
 	*fail = !ReleaseSemaphore (handle, releaseCount, &prevcount);
 
 	return (prevcount);
@@ -1739,8 +1724,6 @@ HANDLE ves_icall_System_Threading_Semaph
 {
 	HANDLE ret;
 	
-	MONO_ARCH_SAVE_REGS;
-	
 	*error = ERROR_SUCCESS;
 	
 	ret = OpenSemaphore (rights, FALSE, mono_string_chars (name));
@@ -1755,8 +1738,6 @@ HANDLE ves_icall_System_Threading_Events
 {
 	HANDLE event;
 	
-	MONO_ARCH_SAVE_REGS;
-
 	*created = TRUE;
 
 	if (name == NULL) {
@@ -1774,21 +1755,15 @@ HANDLE ves_icall_System_Threading_Events
 }
 
 gboolean ves_icall_System_Threading_Events_SetEvent_internal (HANDLE handle) {
-	MONO_ARCH_SAVE_REGS;
-
 	return (SetEvent(handle));
 }
 
 gboolean ves_icall_System_Threading_Events_ResetEvent_internal (HANDLE handle) {
-	MONO_ARCH_SAVE_REGS;
-
 	return (ResetEvent(handle));
 }
 
 void
 ves_icall_System_Threading_Events_CloseEvent_internal (HANDLE handle) {
-	MONO_ARCH_SAVE_REGS;
-
 	CloseHandle (handle);
 }
 
@@ -1798,8 +1773,6 @@ HANDLE ves_icall_System_Threading_Events
 {
 	HANDLE ret;
 	
-	MONO_ARCH_SAVE_REGS;
-	
 	*error = ERROR_SUCCESS;
 	
 	ret = OpenEvent (rights, FALSE, mono_string_chars (name));
@@ -1812,53 +1785,26 @@ HANDLE ves_icall_System_Threading_Events
 
 gint32 ves_icall_System_Threading_Interlocked_Increment_Int (gint32 *location)
 {
-	MONO_ARCH_SAVE_REGS;
-
 	return InterlockedIncrement (location);
 }
 
 gint64 ves_icall_System_Threading_Interlocked_Increment_Long (gint64 *location)
 {
-	gint64 ret;
-
-	MONO_ARCH_SAVE_REGS;
-
-	mono_interlocked_lock ();
-
-	ret = ++ *location;
-	
-	mono_interlocked_unlock ();
-
-	
-	return ret;
+	return InterlockedIncrement64 (location);
 }
 
 gint32 ves_icall_System_Threading_Interlocked_Decrement_Int (gint32 *location)
 {
-	MONO_ARCH_SAVE_REGS;
-
 	return InterlockedDecrement(location);
 }
 
 gint64 ves_icall_System_Threading_Interlocked_Decrement_Long (gint64 * location)
 {
-	gint64 ret;
-
-	MONO_ARCH_SAVE_REGS;
-
-	mono_interlocked_lock ();
-
-	ret = -- *location;
-	
-	mono_interlocked_unlock ();
-
-	return ret;
+	return InterlockedDecrement64 (location);
 }
 
 gint32 ves_icall_System_Threading_Interlocked_Exchange_Int (gint32 *location, gint32 value)
 {
-	MONO_ARCH_SAVE_REGS;
-
 	return InterlockedExchange(location, value);
 }
 
@@ -1879,8 +1825,6 @@ gfloat ves_icall_System_Threading_Interl
 {
 	IntFloatUnion val, ret;
 
-	MONO_ARCH_SAVE_REGS;
-
 	val.fval = value;
 	ret.ival = InterlockedExchange((gint32 *) location, val.ival);
 
@@ -1890,54 +1834,22 @@ gfloat ves_icall_System_Threading_Interl
 gint64 
 ves_icall_System_Threading_Interlocked_Exchange_Long (gint64 *location, gint64 value)
 {
-#if SIZEOF_VOID_P == 8
-	return (gint64) InterlockedExchangePointer((gpointer *) location, (gpointer)value);
-#else
-	gint64 res;
-
-	/* 
-	 * According to MSDN, this function is only atomic with regards to the 
-	 * other Interlocked functions on 32 bit platforms.
-	 */
-	mono_interlocked_lock ();
-	res = *location;
-	*location = value;
-	mono_interlocked_unlock ();
-
-	return res;
-#endif
+	return InterlockedExchange64 (location, value);
 }
 
 gdouble 
 ves_icall_System_Threading_Interlocked_Exchange_Double (gdouble *location, gdouble value)
 {
-#if SIZEOF_VOID_P == 8
 	LongDoubleUnion val, ret;
 
 	val.fval = value;
-	ret.ival = (gint64)InterlockedExchangePointer((gpointer *) location, (gpointer)val.ival);
+	ret.ival = (gint64)InterlockedExchange64((gint64 *) location, val.ival);
 
 	return ret.fval;
-#else
-	gdouble res;
-
-	/* 
-	 * According to MSDN, this function is only atomic with regards to the 
-	 * other Interlocked functions on 32 bit platforms.
-	 */
-	mono_interlocked_lock ();
-	res = *location;
-	*location = value;
-	mono_interlocked_unlock ();
-
-	return res;
-#endif
 }
 
 gint32 ves_icall_System_Threading_Interlocked_CompareExchange_Int(gint32 *location, gint32 value, gint32 comparand)
 {
-	MONO_ARCH_SAVE_REGS;
-
 	return InterlockedCompareExchange(location, value, comparand);
 }
 
@@ -1958,8 +1870,6 @@ gfloat ves_icall_System_Threading_Interl
 {
 	IntFloatUnion val, ret, cmp;
 
-	MONO_ARCH_SAVE_REGS;
-
 	val.fval = value;
 	cmp.fval = comparand;
 	ret.ival = InterlockedCompareExchange((gint32 *) location, val.ival, cmp.ival);
@@ -2034,14 +1944,7 @@ ves_icall_System_Threading_Interlocked_A
 	mono_raise_exception (mono_get_exception_not_implemented (NULL));
 	return 0;
 #else
-	gint32 orig;
-
-	mono_interlocked_lock ();
-	orig = *location;
-	*location = orig + value;
-	mono_interlocked_unlock ();
-
-	return orig + value;
+	return InterlockedAdd (location, value);
 #endif
 }
 
@@ -2053,39 +1956,20 @@ ves_icall_System_Threading_Interlocked_A
 	mono_raise_exception (mono_get_exception_not_implemented (NULL));
 	return 0;
 #else
-	gint64 orig;
-
-	mono_interlocked_lock ();
-	orig = *location;
-	*location = orig + value;
-	mono_interlocked_unlock ();
-
-	return orig + value;
+	return InterlockedAdd64 (location, value);
 #endif
 }
 
 gint64 
 ves_icall_System_Threading_Interlocked_Read_Long (gint64 *location)
 {
-#if SIZEOF_VOID_P == 8
-	/* 64 bit reads are already atomic */
-	return *location;
-#else
-	gint64 res;
-
-	mono_interlocked_lock ();
-	res = *location;
-	mono_interlocked_unlock ();
-
-	return res;
-#endif
+	return InterlockedRead64 (location);
 }
 
 void
 ves_icall_System_Threading_Thread_MemoryBarrier (void)
 {
-	mono_threads_lock ();
-	mono_threads_unlock ();
+	mono_memory_barrier ();
 }
 
 void
@@ -2512,108 +2396,119 @@ void mono_thread_stop (MonoThread *threa
 gint8
 ves_icall_System_Threading_Thread_VolatileRead1 (void *ptr)
 {
-	return *((volatile gint8 *) (ptr));
+	gint8 tmp;
+	mono_atomic_load_acquire (tmp, gint8, (volatile gint8 *) ptr);
+	return tmp;
 }
 
 gint16
 ves_icall_System_Threading_Thread_VolatileRead2 (void *ptr)
 {
-	return *((volatile gint16 *) (ptr));
+	gint16 tmp;
+	mono_atomic_load_acquire (tmp, gint16, (volatile gint16 *) ptr);
+	return tmp;
 }
 
 gint32
 ves_icall_System_Threading_Thread_VolatileRead4 (void *ptr)
 {
-	return *((volatile gint32 *) (ptr));
+	gint32 tmp;
+	mono_atomic_load_acquire (tmp, gint32, (volatile gint32 *) ptr);
+	return tmp;
 }
 
 gint64
 ves_icall_System_Threading_Thread_VolatileRead8 (void *ptr)
 {
-#if SIZEOF_VOID_P == 8
-	return *((volatile gint64 *) (ptr));
-#else
-	return InterlockedCompareExchange64 (ptr, 0, 0); /*Must ensure atomicity of the operation. */
-#endif
+	gint64 tmp;
+	mono_atomic_load_acquire (tmp, gint64, (volatile gint64 *) ptr);
+	return tmp;
 }
 
 void *
 ves_icall_System_Threading_Thread_VolatileReadIntPtr (void *ptr)
 {
-	return (void *)  *((volatile void **) ptr);
+	volatile void *tmp;
+	mono_atomic_load_acquire (tmp, volatile void *, (volatile void **) ptr);
+	return (void *) tmp;
 }
 
 double
 ves_icall_System_Threading_Thread_VolatileReadDouble (void *ptr)
 {
-	return *((volatile double *) (ptr));
+	double tmp;
+	mono_atomic_load_acquire (tmp, double, (volatile double *) ptr);
+	return tmp;
 }
 
 float
 ves_icall_System_Threading_Thread_VolatileReadFloat (void *ptr)
 {
-	return *((volatile float *) (ptr));
+	float tmp;
+	mono_atomic_load_acquire (tmp, float, (volatile float *) ptr);
+	return tmp;
 }
 
 MonoObject*
 ves_icall_System_Threading_Volatile_Read_T (void *ptr)
 {
-	return (MonoObject*)*((volatile MonoObject**)ptr);
+	volatile MonoObject *tmp;
+	mono_atomic_load_acquire (tmp, volatile MonoObject *, (volatile MonoObject **) ptr);
+	return (MonoObject *) tmp;
 }
 
 void
 ves_icall_System_Threading_Thread_VolatileWrite1 (void *ptr, gint8 value)
 {
-	*((volatile gint8 *) ptr) = value;
+	mono_atomic_store_release ((volatile gint8 *) ptr, value);
 }
 
 void
 ves_icall_System_Threading_Thread_VolatileWrite2 (void *ptr, gint16 value)
 {
-	*((volatile gint16 *) ptr) = value;
+	mono_atomic_store_release ((volatile gint16 *) ptr, value);
 }
 
 void
 ves_icall_System_Threading_Thread_VolatileWrite4 (void *ptr, gint32 value)
 {
-	*((volatile gint32 *) ptr) = value;
+	mono_atomic_store_release ((volatile gint32 *) ptr, value);
 }
 
 void
 ves_icall_System_Threading_Thread_VolatileWrite8 (void *ptr, gint64 value)
 {
-	*((volatile gint64 *) ptr) = value;
+	mono_atomic_store_release ((volatile gint64 *) ptr, value);
 }
 
 void
 ves_icall_System_Threading_Thread_VolatileWriteIntPtr (void *ptr, void *value)
 {
-	*((volatile void **) ptr) = value;
+	mono_atomic_store_release ((volatile void **) ptr, value);
 }
 
 void
 ves_icall_System_Threading_Thread_VolatileWriteObject (void *ptr, void *value)
 {
-	mono_gc_wbarrier_generic_store (ptr, value);
+	mono_gc_wbarrier_generic_store_atomic (ptr, value);
 }
 
 void
 ves_icall_System_Threading_Thread_VolatileWriteDouble (void *ptr, double value)
 {
-	*((volatile double *) ptr) = value;
+	mono_atomic_store_release ((volatile double *) ptr, value);
 }
 
 void
 ves_icall_System_Threading_Thread_VolatileWriteFloat (void *ptr, float value)
 {
-	*((volatile float *) ptr) = value;
+	mono_atomic_store_release ((volatile float *) ptr, value);
 }
 
 void
 ves_icall_System_Threading_Volatile_Write_T (void *ptr, MonoObject *value)
 {
-	*((volatile MonoObject **) ptr) = value;
-	mono_gc_wbarrier_generic_nostore (ptr);
+	mono_gc_wbarrier_generic_store_atomic (ptr, value);
 }
 
 void
--- mono-3.2.3+dfsg.orig/mono/tests/sgen-descriptors.cs
+++ mono-3.2.3+dfsg/mono/tests/sgen-descriptors.cs
@@ -1,4 +1,5 @@
 using System;
+using System.Runtime.InteropServices;
 
 public struct SmallMixed
 {
@@ -47,6 +48,13 @@ public class HugePtrFree {
 	public LargeStruct2 c;
 }
 
+[StructLayout (LayoutKind.Sequential)]
+public class Non32bitBitmap {
+	public object o;
+	public long i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15, i16, i17, i18, i19, i20, i21, i22, i23, i24, i25, i26, i27, i28, i29, i30, i31, i32, i33, i34, i35;
+	public object o2;
+}
+
 /*
 This is a stress test for descriptors.
 */
@@ -54,10 +62,10 @@ class Driver {
 	static char[] FOO = new char[] { 'f', 'o', 'b' };
 
 	static void Fill (int cycles) {
-		object[] root = new object [12];
+		object[] root = new object [13];
 		object[] current = root;
 		for (int i = 0; i < cycles; ++i) {
-			current [0] = new object [12];
+			current [0] = new object [13];
 			current [1] = new int [6];
 			current [2] = new int [2,3];
 			current [3] = new string (FOO);
@@ -72,6 +80,9 @@ class Driver {
 				current [10] = new HugePtrFree ();
 			if ((i %  10000) == 0)
 				current [11] = new LargeStruct2 [1];
+
+			/* Test for 64 bit bitmap descriptors (#14834) */
+			current [12] = new Non32bitBitmap () { o = new object (), i32 = 1, i33 = 1, i34 = 1, i35 = 1, o2 = new object () };
 	
 			current = (object[])current [0];
 		}
--- mono-3.2.3+dfsg.orig/mono/tests/Makefile.am
+++ mono-3.2.3+dfsg/mono/tests/Makefile.am
@@ -338,7 +338,6 @@ BASE_TEST_CS_SRC=		\
 	modules.cs	\
 	bug-81673.cs	\
 	bug-81691.cs	\
-	bug-80307.cs	\
 	bug-415577.cs	\
 	filter-stack.cs	\
 	vararg2.cs	\
--- mono-3.2.3+dfsg.orig/mono/utils/atomic.h
+++ mono-3.2.3+dfsg/mono/utils/atomic.h
@@ -11,16 +11,6 @@
 #ifndef _WAPI_ATOMIC_H_
 #define _WAPI_ATOMIC_H_
 
-#if defined(__NetBSD__)
-#include <sys/param.h>
-
-#if __NetBSD_Version__ > 499004000
-#include <sys/atomic.h>
-#define HAVE_ATOMIC_OPS
-#endif
-
-#endif
-
 #include "config.h"
 #include <glib.h>
 
@@ -32,7 +22,6 @@
 #if defined(__WIN32__) || defined(_WIN32)
 
 #include <windows.h>
-#define HAS_64BITS_ATOMICS 1
 
 /* mingw is missing InterlockedCompareExchange64 () from winbase.h */
 #ifdef __MINGW32__
@@ -42,6 +31,30 @@ static inline gint64 InterlockedCompareE
 }
 #endif
 
+/* And now for some dirty hacks... The Windows API doesn't
+ * provide any useful primitives for this (other than getting
+ * into architecture-specific madness), so use CAS. */
+
+static inline gint32 InterlockedRead(volatile gint32 *src)
+{
+	return InterlockedCompareExchange (src, 0, 0);
+}
+
+static inline gint64 InterlockedRead64(volatile gint64 *src)
+{
+	return InterlockedCompareExchange64 (src, 0, 0);
+}
+
+static inline void InterlockedWrite(volatile gint32 *dst, gint32 val)
+{
+	InterlockedExchange (dst, val);
+}
+
+static inline void InterlockedWrite64(volatile gint64 *dst, gint64 val)
+{
+	InterlockedExchange64 (dst, val);
+}
+
 /* Prefer GCC atomic ops if the target supports it (see configure.in). */
 #elif defined(USE_GCC_ATOMIC_OPS)
 
@@ -56,6 +69,11 @@ static inline gpointer InterlockedCompar
 	return __sync_val_compare_and_swap (dest, comp, exch);
 }
 
+static inline gint32 InterlockedAdd(volatile gint32 *dest, gint32 add)
+{
+	return __sync_add_and_fetch (dest, add);
+}
+
 static inline gint32 InterlockedIncrement(volatile gint32 *val)
 {
 	return __sync_add_and_fetch (val, 1);
@@ -63,7 +81,7 @@ static inline gint32 InterlockedIncremen
 
 static inline gint32 InterlockedDecrement(volatile gint32 *val)
 {
-	return __sync_add_and_fetch (val, -1);
+	return __sync_sub_and_fetch (val, 1);
 }
 
 static inline gint32 InterlockedExchange(volatile gint32 *val, gint32 new_val)
@@ -90,59 +108,127 @@ static inline gint32 InterlockedExchange
 	return __sync_fetch_and_add (val, add);
 }
 
-#if defined (TARGET_OSX)
+static inline gint32 InterlockedRead(volatile gint32 *src)
+{
+	/* Kind of a hack, but GCC doesn't give us anything better, and it's
+	   certainly not as bad as using a CAS loop. */
+	return __sync_fetch_and_add (src, 0);
+}
+
+static inline void InterlockedWrite(volatile gint32 *dst, gint32 val)
+{
+	/* Nothing useful from GCC at all, so fall back to CAS. */
+	InterlockedExchange (dst, val);
+}
+
+#if defined (TARGET_OSX) || defined (__arm__) || (defined (__mips__) && !defined (__mips64)) || (defined (__powerpc__) && !defined (__powerpc64__))
 #define BROKEN_64BIT_ATOMICS_INTRINSIC 1
 #endif
 
-
 #if !defined (BROKEN_64BIT_ATOMICS_INTRINSIC)
-#define HAS_64BITS_ATOMICS 1
 
 static inline gint64 InterlockedCompareExchange64(volatile gint64 *dest, gint64 exch, gint64 comp)
 {
 	return __sync_val_compare_and_swap (dest, comp, exch);
 }
 
-#endif
+static inline gint64 InterlockedAdd64(volatile gint64 *dest, gint64 add)
+{
+	return __sync_add_and_fetch (dest, add);
+}
 
+static inline gint64 InterlockedIncrement64(volatile gint64 *val)
+{
+	return __sync_add_and_fetch (val, 1);
+}
 
-#elif defined(__NetBSD__) && defined(HAVE_ATOMIC_OPS)
+static inline gint64 InterlockedDecrement64(volatile gint64 *val)
+{
+	return __sync_sub_and_fetch (val, 1);
+}
 
-static inline gint32 InterlockedCompareExchange(volatile gint32 *dest,
-       gint32 exch, gint32 comp)
+static inline gint64 InterlockedExchangeAdd64(volatile gint64 *val, gint64 add)
 {
-       return atomic_cas_32((uint32_t*)dest, comp, exch);
+	return __sync_fetch_and_add (val, add);
 }
 
-static inline gpointer InterlockedCompareExchangePointer(volatile gpointer *dest, gpointer exch, gpointer comp)
+static inline gint64 InterlockedRead64(volatile gint64 *src)
 {
-       return atomic_cas_ptr(dest, comp, exch);
+	/* Kind of a hack, but GCC doesn't give us anything better. */
+	return __sync_fetch_and_add (src, 0);
 }
 
-static inline gint32 InterlockedIncrement(volatile gint32 *val)
+#else
+
+/* Implement 64-bit cmpxchg by hand or emulate it. */
+extern gint64 InterlockedCompareExchange64(volatile gint64 *dest, gint64 exch, gint64 comp);
+
+/* Implement all other 64-bit atomics in terms of a specialized CAS
+ * in this case, since chances are that the other 64-bit atomic
+ * intrinsics are broken too.
+ */
+
+static inline gint64 InterlockedExchangeAdd64(volatile gint64 *dest, gint64 add)
 {
-       return atomic_inc_32_nv((uint32_t*)val);
+	gint64 old_val;
+	do {
+		old_val = *dest;
+	} while (InterlockedCompareExchange64 (dest, old_val + add, old_val) != old_val);
+	return old_val;
 }
 
-static inline gint32 InterlockedDecrement(volatile gint32 *val)
+static inline gint64 InterlockedIncrement64(volatile gint64 *val)
 {
-       return atomic_dec_32_nv((uint32_t*)val);
+	gint64 get, set;
+	do {
+		get = *val;
+		set = get + 1;
+	} while (InterlockedCompareExchange64 (val, set, get) != get);
+	return set;
 }
 
-static inline gint32 InterlockedExchange(volatile gint32 *val, gint32 new_val)
+static inline gint64 InterlockedDecrement64(volatile gint64 *val)
 {
-       return atomic_swap_32((uint32_t*)val, new_val);
+	gint64 get, set;
+	do {
+		get = *val;
+		set = get - 1;
+	} while (InterlockedCompareExchange64 (val, set, get) != get);
+	return set;
 }
 
-static inline gpointer InterlockedExchangePointer(volatile gpointer *val,
-               gpointer new_val)
+static inline gint64 InterlockedAdd64(volatile gint64 *dest, gint64 add)
 {
-       return atomic_swap_ptr(val, new_val);
+	gint64 get, set;
+	do {
+		get = *dest;
+		set = get + add;
+	} while (InterlockedCompareExchange64 (dest, set, get) != get);
+	return set;
 }
 
-static inline gint32 InterlockedExchangeAdd(volatile gint32 *val, gint32 add)
+static inline gint64 InterlockedRead64(volatile gint64 *src)
+{
+	return InterlockedCompareExchange64 (src, 0, 0);
+}
+
+#endif
+
+/* We always implement this in terms of a 64-bit cmpxchg since
+ * GCC doesn't have an intrisic to model it anyway. */
+static inline gint64 InterlockedExchange64(volatile gint64 *val, gint64 new_val)
+{
+	gint64 old_val;
+	do {
+		old_val = *val;
+	} while (InterlockedCompareExchange64 (val, new_val, old_val) != old_val);
+	return old_val;
+}
+
+static inline void InterlockedWrite64(volatile gint64 *dst, gint64 val)
 {
-       return atomic_add_32_nv((uint32_t*)val, add) - add;
+	/* Nothing useful from GCC at all, so fall back to CAS. */
+	InterlockedExchange64 (dst, val);
 }
 
 #elif (defined(sparc) || defined (__sparc__)) && defined(__GNUC__)
@@ -305,126 +391,6 @@ static inline gint32 InterlockedExchange
         return ret;
 }
 
-#elif __s390x__
-
-static inline gint32 
-InterlockedCompareExchange(volatile gint32 *dest,
-			   gint32 exch, gint32 comp)
-{
-	gint32 old;
-
-	__asm__ __volatile__ ("\tLA\t1,%0\n"
-			      "\tLR\t%1,%3\n"
-			      "\tCS\t%1,%2,0(1)\n"
-			      : "+m" (*dest), "=&r" (old)
-			      : "r" (exch), "r" (comp)
-			      : "1", "cc");	
-	return(old);
-}
-
-static inline gpointer 
-InterlockedCompareExchangePointer(volatile gpointer *dest, 
-				  gpointer exch, 
-			          gpointer comp)
-{
-	gpointer old;
-
-	__asm__ __volatile__ ("\tLA\t1,%0\n"
-			      "\tLGR\t%1,%3\n"
-			      "\tCSG\t%1,%2,0(1)\n"
-			      : "+m" (*dest), "=&r" (old)
-			      : "r" (exch), "r" (comp)
-			      : "1", "cc");
-
-	return(old);
-}
-
-static inline gint32 
-InterlockedIncrement(volatile gint32 *val)
-{
-	gint32 tmp;
-	
-	__asm__ __volatile__ ("\tLA\t2,%1\n"
-			      "0:\tLGF\t%0,%1\n"
-			      "\tLGFR\t1,%0\n"
-			      "\tAGHI\t1,1\n"
-			      "\tCS\t%0,1,0(2)\n"
-			      "\tJNZ\t0b\n"
-			      "\tLGFR\t%0,1"
-			      : "=r" (tmp), "+m" (*val)
-			      : : "1", "2", "cc");
-
-	return(tmp);
-}
-
-static inline gint32 
-InterlockedDecrement(volatile gint32 *val)
-{
-	gint32 tmp;
-	
-	__asm__ __volatile__ ("\tLA\t2,%1\n"
-			      "0:\tLGF\t%0,%1\n"
-			      "\tLGFR\t1,%0\n"
-			      "\tAGHI\t1,-1\n"
-			      "\tCS\t%0,1,0(2)\n"
-			      "\tJNZ\t0b\n"
-			      "\tLGFR\t%0,1"
-			      : "=r" (tmp), "+m" (*val)
-			      : : "1", "2", "cc");
-
-	return(tmp);
-}
-
-static inline gint32 
-InterlockedExchange(volatile gint32 *val, gint32 new_val)
-{
-	gint32 ret;
-	
-	__asm__ __volatile__ ("\tLA\t1,%0\n"
-			      "0:\tL\t%1,%0\n"
-			      "\tCS\t%1,%2,0(1)\n"
-			      "\tJNZ\t0b"
-			      : "+m" (*val), "=&r" (ret)
-			      : "r" (new_val)
-			      : "1", "cc");
-
-	return(ret);
-}
-
-static inline gpointer
-InterlockedExchangePointer(volatile gpointer *val, gpointer new_val)
-{
-	gpointer ret;
-	
-	__asm__ __volatile__ ("\tLA\t1,%0\n"
-			      "0:\tLG\t%1,%0\n"
-			      "\tCSG\t%1,%2,0(1)\n"
-			      "\tJNZ\t0b"
-			      : "+m" (*val), "=&r" (ret)
-			      : "r" (new_val)
-			      : "1", "cc");
-
-	return(ret);
-}
-
-static inline gint32 
-InterlockedExchangeAdd(volatile gint32 *val, gint32 add)
-{
-	gint32 ret;
-
-	__asm__ __volatile__ ("\tLA\t2,%1\n"
-			      "0:\tLGF\t%0,%1\n"
-			      "\tLGFR\t1,%0\n"
-			      "\tAGR\t1,%2\n"
-			      "\tCS\t%0,1,0(2)\n"
-			      "\tJNZ\t0b"
-			      : "=&r" (ret), "+m" (*val)
-			      : "r" (add) 
-			      : "1", "2", "cc");
-	
-	return(ret);
-}
-
 #elif defined(__ia64__)
 
 #ifdef __INTEL_COMPILER
@@ -546,17 +512,24 @@ static inline gint32 InterlockedExchange
 #define WAPI_NO_ATOMIC_ASM
 
 extern gint32 InterlockedCompareExchange(volatile gint32 *dest, gint32 exch, gint32 comp);
+extern gint64 InterlockedCompareExchange64(volatile gint64 *dest, gint64 exch, gint64 comp);
 extern gpointer InterlockedCompareExchangePointer(volatile gpointer *dest, gpointer exch, gpointer comp);
+extern gint32 InterlockedAdd(volatile gint32 *dest, gint32 add);
+extern gint64 InterlockedAdd64(volatile gint64 *dest, gint64 add);
 extern gint32 InterlockedIncrement(volatile gint32 *dest);
+extern gint64 InterlockedIncrement64(volatile gint64 *dest);
 extern gint32 InterlockedDecrement(volatile gint32 *dest);
+extern gint64 InterlockedDecrement64(volatile gint64 *dest);
 extern gint32 InterlockedExchange(volatile gint32 *dest, gint32 exch);
+extern gint64 InterlockedExchange64(volatile gint64 *dest, gint64 exch);
 extern gpointer InterlockedExchangePointer(volatile gpointer *dest, gpointer exch);
 extern gint32 InterlockedExchangeAdd(volatile gint32 *dest, gint32 add);
+extern gint64 InterlockedExchangeAdd64(volatile gint64 *dest, gint64 add);
+extern gint32 InterlockedRead(volatile gint32 *src);
+extern gint64 InterlockedRead64(volatile gint64 *src);
+extern void InterlockedWrite(volatile gint32 *dst, gint32 val);
+extern void InterlockedWrite64(volatile gint64 *dst, gint64 val);
 
 #endif
 
-#ifndef HAS_64BITS_ATOMICS
-extern gint64 InterlockedCompareExchange64(volatile gint64 *dest, gint64 exch, gint64 comp);
-#endif
-
 #endif /* _WAPI_ATOMIC_H_ */
--- mono-3.2.3+dfsg.orig/mono/utils/mono-hwcap-arm.h
+++ mono-3.2.3+dfsg/mono/utils/mono-hwcap-arm.h
@@ -8,6 +8,8 @@ extern gboolean mono_hwcap_arm_is_v6;
 extern gboolean mono_hwcap_arm_is_v7;
 extern gboolean mono_hwcap_arm_is_v7s;
 extern gboolean mono_hwcap_arm_has_vfp;
+extern gboolean mono_hwcap_arm_has_vfp3;
+extern gboolean mono_hwcap_arm_has_vfp3_d16;
 extern gboolean mono_hwcap_arm_has_thumb;
 extern gboolean mono_hwcap_arm_has_thumb2;
 
--- mono-3.2.3+dfsg.orig/mono/utils/mono-sigcontext.h
+++ mono-3.2.3+dfsg/mono/utils/mono-sigcontext.h
@@ -16,14 +16,14 @@
 
 #if defined(TARGET_X86)
 
-#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__DragonFly__)
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__DragonFly__)
 #include <ucontext.h>
 #endif
 #if defined(__APPLE__)
 #include <AvailabilityMacros.h>
 #endif
 
-#if defined(__FreeBSD__) || defined(__DragonFly__)
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
 	#define UCONTEXT_REG_EAX(ctx) (((ucontext_t*)(ctx))->uc_mcontext.mc_eax)
 	#define UCONTEXT_REG_EBX(ctx) (((ucontext_t*)(ctx))->uc_mcontext.mc_ebx)
 	#define UCONTEXT_REG_ECX(ctx) (((ucontext_t*)(ctx))->uc_mcontext.mc_ecx)
@@ -154,7 +154,7 @@ typedef struct ucontext {
 
 #elif defined(TARGET_AMD64)
 
-#if defined(__FreeBSD__)
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
 #include <ucontext.h>
 #endif
 
@@ -176,7 +176,7 @@ typedef struct ucontext {
 	#define UCONTEXT_REG_R13(ctx) (((ucontext_t*)(ctx))->uc_mcontext->__ss.__r13)
 	#define UCONTEXT_REG_R14(ctx) (((ucontext_t*)(ctx))->uc_mcontext->__ss.__r14)
 	#define UCONTEXT_REG_R15(ctx) (((ucontext_t*)(ctx))->uc_mcontext->__ss.__r15)
-#elif defined(__FreeBSD__)
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
 	#define UCONTEXT_REG_RAX(ctx) (((ucontext_t*)(ctx))->uc_mcontext.mc_rax)
 	#define UCONTEXT_REG_RBX(ctx) (((ucontext_t*)(ctx))->uc_mcontext.mc_rbx)
 	#define UCONTEXT_REG_RCX(ctx) (((ucontext_t*)(ctx))->uc_mcontext.mc_rcx)
--- mono-3.2.3+dfsg.orig/mono/utils/atomic.c
+++ mono-3.2.3+dfsg/mono/utils/atomic.c
@@ -13,12 +13,14 @@
 
 #include <mono/utils/atomic.h>
 
-#if defined (WAPI_NO_ATOMIC_ASM) || !defined (HAS_64BITS_ATOMIC)
+#if defined (WAPI_NO_ATOMIC_ASM) || defined (BROKEN_64BIT_ATOMICS_INTRINSIC)
 
 #include <pthread.h>
 
 static pthread_mutex_t spin = PTHREAD_MUTEX_INITIALIZER;
 
+#define NEED_64BIT_CMPXCHG_FALLBACK
+
 #endif
 
 #ifdef WAPI_NO_ATOMIC_ASM
@@ -82,6 +84,52 @@ gpointer InterlockedCompareExchangePoint
 	return(old);
 }
 
+gint32 InterlockedAdd(volatile gint32 *dest, gint32 add)
+{
+	gint32 ret;
+	int thr_ret;
+
+	mono_once(&spin_once, spin_init);
+
+	pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+			      (void *)&spin);
+	thr_ret = pthread_mutex_lock(&spin);
+	g_assert (thr_ret == 0);
+
+	*dest += add;
+	ret= *dest;
+
+	thr_ret = pthread_mutex_unlock(&spin);
+	g_assert (thr_ret == 0);
+
+	pthread_cleanup_pop (0);
+
+	return(ret);
+}
+
+gint64 InterlockedAdd64(volatile gint64 *dest, gint64 add)
+{
+	gint64 ret;
+	int thr_ret;
+
+	mono_once(&spin_once, spin_init);
+
+	pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+			      (void *)&spin);
+	thr_ret = pthread_mutex_lock(&spin);
+	g_assert (thr_ret == 0);
+
+	*dest += add;
+	ret= *dest;
+
+	thr_ret = pthread_mutex_unlock(&spin);
+	g_assert (thr_ret == 0);
+
+	pthread_cleanup_pop (0);
+
+	return(ret);
+}
+
 gint32 InterlockedIncrement(volatile gint32 *dest)
 {
 	gint32 ret;
@@ -105,6 +153,29 @@ gint32 InterlockedIncrement(volatile gin
 	return(ret);
 }
 
+gint64 InterlockedIncrement64(volatile gint64 *dest)
+{
+	gint64 ret;
+	int thr_ret;
+
+	mono_once(&spin_once, spin_init);
+
+	pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+			      (void *)&spin);
+	thr_ret = pthread_mutex_lock(&spin);
+	g_assert (thr_ret == 0);
+
+	(*dest)++;
+	ret= *dest;
+
+	thr_ret = pthread_mutex_unlock(&spin);
+	g_assert (thr_ret == 0);
+
+	pthread_cleanup_pop (0);
+
+	return(ret);
+}
+
 gint32 InterlockedDecrement(volatile gint32 *dest)
 {
 	gint32 ret;
@@ -128,6 +199,29 @@ gint32 InterlockedDecrement(volatile gin
 	return(ret);
 }
 
+gint64 InterlockedDecrement64(volatile gint64 *dest)
+{
+	gint64 ret;
+	int thr_ret;
+
+	mono_once(&spin_once, spin_init);
+
+	pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+			      (void *)&spin);
+	thr_ret = pthread_mutex_lock(&spin);
+	g_assert (thr_ret == 0);
+
+	(*dest)--;
+	ret= *dest;
+
+	thr_ret = pthread_mutex_unlock(&spin);
+	g_assert (thr_ret == 0);
+
+	pthread_cleanup_pop (0);
+
+	return(ret);
+}
+
 gint32 InterlockedExchange(volatile gint32 *dest, gint32 exch)
 {
 	gint32 ret;
@@ -151,6 +245,29 @@ gint32 InterlockedExchange(volatile gint
 	return(ret);
 }
 
+gint64 InterlockedExchange64(volatile gint64 *dest, gint64 exch)
+{
+	gint64 ret;
+	int thr_ret;
+
+	mono_once(&spin_once, spin_init);
+
+	pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+			      (void *)&spin);
+	thr_ret = pthread_mutex_lock(&spin);
+	g_assert (thr_ret == 0);
+
+	ret=*dest;
+	*dest=exch;
+
+	thr_ret = pthread_mutex_unlock(&spin);
+	g_assert (thr_ret == 0);
+
+	pthread_cleanup_pop (0);
+
+	return(ret);
+}
+
 gpointer InterlockedExchangePointer(volatile gpointer *dest, gpointer exch)
 {
 	gpointer ret;
@@ -197,40 +314,116 @@ gint32 InterlockedExchangeAdd(volatile g
 	return(ret);
 }
 
-#endif
+gint64 InterlockedExchangeAdd64(volatile gint64 *dest, gint64 add)
+{
+	gint64 ret;
+	int thr_ret;
+	
+	mono_once(&spin_once, spin_init);
+	
+	pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+			      (void *)&spin);
+	thr_ret = pthread_mutex_lock(&spin);
+	g_assert (thr_ret == 0);
 
-#ifndef HAS_64BITS_ATOMICS
+	ret= *dest;
+	*dest+=add;
+	
+	thr_ret = pthread_mutex_unlock(&spin);
+	g_assert (thr_ret == 0);
 
-#if defined (TARGET_MACH) && defined (TARGET_ARM) && (defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7S__))
+	pthread_cleanup_pop (0);
 
-gint64 InterlockedCompareExchange64(volatile gint64 *dest, gint64 exch, gint64 comp)  __attribute__ ((naked));
+	return(ret);
+}
 
-gint64
-InterlockedCompareExchange64(volatile gint64 *dest, gint64 exch, gint64 comp)
+gint32 InterlockedRead(volatile gint32 *src)
 {
-	__asm__ (
-	"push {r4, r5, r6, r7}\n"
-	"ldr r4, [sp, #16]\n"
-	"dmb\n"
-"1:\n"
-	"ldrexd	r6, r7, [r0]\n"
-	"cmp	r7, r4\n"
-	"bne 2f\n"
-	"cmp	r6, r3\n"
-	"bne	2f\n"
-	"strexd	r5, r1, r2, [r0]\n"
-	"cmp	r5, #0\n"
-	"bne	1b\n"
-"2:\n"
-	"dmb\n"
-	"mov	r0, r6\n"
-	"mov	r1, r7\n"
-	"pop {r4, r5, r6, r7}\n"
-	"bx	lr\n"
-	);
+	gint32 ret;
+	int thr_ret;
+	
+	mono_once(&spin_once, spin_init);
+	
+	pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+			      (void *)&spin);
+	thr_ret = pthread_mutex_lock(&spin);
+	g_assert (thr_ret == 0);
+
+	ret= *src;
+	
+	thr_ret = pthread_mutex_unlock(&spin);
+	g_assert (thr_ret == 0);
+
+	pthread_cleanup_pop (0);
+
+	return(ret);
 }
 
-#elif defined (TARGET_MACH) && (defined (TARGET_X86) || defined (TARGET_AMD64))
+gint64 InterlockedRead64(volatile gint64 *src)
+{
+	gint64 ret;
+	int thr_ret;
+	
+	mono_once(&spin_once, spin_init);
+	
+	pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+			      (void *)&spin);
+	thr_ret = pthread_mutex_lock(&spin);
+	g_assert (thr_ret == 0);
+
+	ret= *src;
+	
+	thr_ret = pthread_mutex_unlock(&spin);
+	g_assert (thr_ret == 0);
+
+	pthread_cleanup_pop (0);
+
+	return(ret);
+}
+
+void InterlockedWrite(volatile gint32 *dst, gint32 val)
+{
+	int thr_ret;
+	
+	mono_once(&spin_once, spin_init);
+	
+	pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+			      (void *)&spin);
+	thr_ret = pthread_mutex_lock(&spin);
+	g_assert (thr_ret == 0);
+
+	*dst=val;
+	
+	thr_ret = pthread_mutex_unlock(&spin);
+	g_assert (thr_ret == 0);
+	
+	pthread_cleanup_pop (0);
+}
+
+void InterlockedWrite64(volatile gint64 *dst, gint64 val)
+{
+	int thr_ret;
+	
+	mono_once(&spin_once, spin_init);
+	
+	pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+			      (void *)&spin);
+	thr_ret = pthread_mutex_lock(&spin);
+	g_assert (thr_ret == 0);
+
+	*dst=val;
+	
+	thr_ret = pthread_mutex_unlock(&spin);
+	g_assert (thr_ret == 0);
+	
+	pthread_cleanup_pop (0);
+}
+
+#endif
+
+#if defined (NEED_64BIT_CMPXCHG_FALLBACK)
+
+#if defined (TARGET_OSX)
 
 gint64
 InterlockedCompareExchange64(volatile gint64 *dest, gint64 exch, gint64 comp)
@@ -238,6 +431,12 @@ InterlockedCompareExchange64(volatile gi
 	return __sync_val_compare_and_swap (dest, comp, exch);
 }
 
+#elif defined (HAVE_64BIT_CMPXCHG_FALLBACK)
+
+#ifdef ENABLE_EXTENSION_MODULE
+#include "../../../mono-extensions/mono/utils/atomic.c"
+#endif
+
 #else
 
 gint64
@@ -256,4 +455,5 @@ InterlockedCompareExchange64(volatile gi
 }
 
 #endif
+
 #endif
--- mono-3.2.3+dfsg.orig/mono/utils/mono-hwcap-arm.c
+++ mono-3.2.3+dfsg/mono/utils/mono-hwcap-arm.c
@@ -35,6 +35,8 @@ gboolean mono_hwcap_arm_is_v6 = FALSE;
 gboolean mono_hwcap_arm_is_v7 = FALSE;
 gboolean mono_hwcap_arm_is_v7s = FALSE;
 gboolean mono_hwcap_arm_has_vfp = FALSE;
+gboolean mono_hwcap_arm_has_vfp3 = FALSE;
+gboolean mono_hwcap_arm_has_vfp3_d16 = FALSE;
 gboolean mono_hwcap_arm_has_thumb = FALSE;
 gboolean mono_hwcap_arm_has_thumb2 = FALSE;
 
@@ -60,6 +62,14 @@ mono_hwcap_arch_init (void)
 		if (hwcap & 0x00000064)
 			mono_hwcap_arm_has_vfp = TRUE;
 
+		/* HWCAP_ARM_VFPv3 */
+		if (hwcap & 0x00002000)
+			mono_hwcap_arm_has_vfp3 = TRUE;
+
+		/* HWCAP_ARM_VFPv3D16 */
+		if (hwcap & 0x00004000)
+			mono_hwcap_arm_has_vfp3_d16 = TRUE;
+
 		/* TODO: Find a way to detect Thumb 2. */
 	}
 
@@ -136,6 +146,12 @@ mono_hwcap_arch_init (void)
 				if (strstr (line, "vfp"))
 					mono_hwcap_arm_has_vfp = TRUE;
 
+				if (strstr (line, "vfpv3"))
+					mono_hwcap_arm_has_vfp3 = TRUE;
+
+				if (strstr (line, "vfpv3-d16"))
+					mono_hwcap_arm_has_vfp3_d16 = TRUE;
+
 				continue;
 			}
 		}
@@ -154,6 +170,8 @@ mono_hwcap_print(FILE *f)
 	g_fprintf (f, "mono_hwcap_arm_is_v7 = %i\n", mono_hwcap_arm_is_v7);
 	g_fprintf (f, "mono_hwcap_arm_is_v7s = %i\n", mono_hwcap_arm_is_v7s);
 	g_fprintf (f, "mono_hwcap_arm_has_vfp = %i\n", mono_hwcap_arm_has_vfp);
+	g_fprintf (f, "mono_hwcap_arm_has_vfp3 = %i\n", mono_hwcap_arm_has_vfp3);
+	g_fprintf (f, "mono_hwcap_arm_has_vfp3_d16 = %i\n", mono_hwcap_arm_has_vfp3_d16);
 	g_fprintf (f, "mono_hwcap_arm_has_thumb = %i\n", mono_hwcap_arm_has_thumb);
 	g_fprintf (f, "mono_hwcap_arm_has_thumb2 = %i\n", mono_hwcap_arm_has_thumb2);
 }
--- mono-3.2.3+dfsg.orig/mono/arch/mips/mips-codegen.h
+++ mono-3.2.3+dfsg/mono/arch/mips/mips-codegen.h
@@ -334,7 +334,7 @@ enum {
 /* misc and coprocessor ops */
 #define mips_move(c,dest,src) mips_addu(c,dest,src,mips_zero)
 #define mips_dmove(c,dest,src) mips_daddu(c,dest,src,mips_zero)
-#define mips_nop(c) mips_sll(c,0,0,0)
+#define mips_nop(c) mips_or(c,mips_at,mips_at,0)
 #define mips_break(c,code) mips_emit32(c, ((code)<<6)|13)
 #define mips_mfhi(c,dest) mips_format_r(c,0,0,0,dest,0,16)
 #define mips_mflo(c,dest) mips_format_r(c,0,0,0,dest,0,18)
--- mono-3.2.3+dfsg.orig/msvc/mono.def
+++ mono-3.2.3+dfsg/msvc/mono.def
@@ -331,6 +331,7 @@ mono_gc_walk_heap
 mono_gc_wbarrier_arrayref_copy
 mono_gc_wbarrier_generic_nostore
 mono_gc_wbarrier_generic_store
+mono_gc_wbarrier_generic_store_atomic
 mono_gc_wbarrier_object_copy
 mono_gc_wbarrier_set_arrayref
 mono_gc_wbarrier_set_field
--- mono-3.2.3+dfsg.orig/docs/public-api
+++ mono-3.2.3+dfsg/docs/public-api
@@ -307,6 +307,7 @@ mono_gc_out_of_memory
 mono_gc_wbarrier_arrayref_copy
 mono_gc_wbarrier_generic_nostore
 mono_gc_wbarrier_generic_store
+mono_gc_wbarrier_generic_store_atomic
 mono_gc_wbarrier_object_copy
 mono_gc_wbarrier_set_arrayref
 mono_gc_wbarrier_set_field
--- mono-3.2.3+dfsg.orig/docs/current-api
+++ mono-3.2.3+dfsg/docs/current-api
@@ -307,6 +307,7 @@ mono_gc_out_of_memory
 mono_gc_wbarrier_arrayref_copy
 mono_gc_wbarrier_generic_nostore
 mono_gc_wbarrier_generic_store
+mono_gc_wbarrier_generic_store_atomic
 mono_gc_wbarrier_object_copy
 mono_gc_wbarrier_set_arrayref
 mono_gc_wbarrier_set_field
--- mono-3.2.3+dfsg.orig/mcs/class/Mono.WebBrowser/Mono.WebBrowser.dll.sources
+++ mono-3.2.3+dfsg/mcs/class/Mono.WebBrowser/Mono.WebBrowser.dll.sources
@@ -133,6 +133,9 @@ Mono.Mozilla/interfaces/nsIWebNavigation
 Mono.Mozilla/interfaces/extras/NodeType.cs
 Mono.Mozilla/interfaces/extras/nsIWriteSegmentFun.cs
 Mono.Mozilla/interfaces/extras/Options.cs
+Mono.NullBrowser/Base.cs
+Mono.NullBrowser/WebBrowser.cs
+Mono.NullBrowser/DOM/Navigation.cs
 Mono.WebBrowser/DOM/IDocumentType.cs
 Mono.WebBrowser/DOM/IDOMImplementation.cs
 Mono.WebBrowser/DOM/IMediaList.cs
--- /dev/null
+++ mono-3.2.3+dfsg/mcs/class/Mono.WebBrowser/Mono.NullBrowser/WebBrowser.cs
@@ -0,0 +1,414 @@
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// Copyright (c) 2007, 2008 Novell, Inc.
+// Copyright (c) 2013 Jo Shields
+//
+// Authors:
+//	Andreia Gaita (avidigal@novell.com)
+//	Jo Shields (directhex@apebox.org)
+//
+
+#undef debug
+
+using System;
+using System.Collections;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Diagnostics;
+using Mono.WebBrowser;
+using Mono.WebBrowser.DOM;
+
+namespace Mono.NullBrowser
+{
+	internal class WebBrowser : IWebBrowser
+	{
+		bool loaded;
+		internal bool created = false;
+		bool creating = false;
+
+                internal DOM.Navigation navigation;
+
+		internal Platform platform;
+		internal Platform enginePlatform;
+		System.ComponentModel.EventHandlerList events;
+		System.ComponentModel.EventHandlerList domEvents;
+
+		string statusText;
+
+		bool streamingMode;
+		
+		internal Hashtable documents;
+
+		int width;
+		int height;
+		bool isDirty;
+		
+		public WebBrowser (Platform platform)
+		{
+			this.platform = platform;
+			loaded = Base.Init (this, platform);
+			documents = new Hashtable ();
+		}
+
+		public bool Load (IntPtr handle, int width, int height)
+		{
+			loaded = Base.Bind (this, handle, width, height);
+			return loaded;
+		}
+
+		bool Created {
+			get {
+				if (!creating && !created) {
+					creating = true;
+					created = Base.Create (this);
+					if (created && isDirty) {
+						isDirty = false;
+						Base.Resize (this, width, height);
+					}
+				}
+				return created;
+			}
+		}
+
+		public void Shutdown ()
+		{
+			Base.Shutdown (this);
+		}
+		
+		internal void Reset ()
+		{
+			this.DomEvents.Dispose ();
+			this.domEvents = null;
+			this.documents.Clear ();
+		}
+
+		public bool Initialized {
+			get { return this.loaded; }
+		}
+		
+		public IWindow Window {
+			get {
+				return null;
+			}
+		}
+
+		public IDocument Document {
+			get {
+				return null;
+			}
+		}
+
+		public INavigation Navigation {
+			get {
+                                if (!Created) return null;
+
+                                if (navigation == null) {
+
+                                        navigation = new DOM.Navigation ();
+                                }
+                                return navigation as INavigation;
+			}
+		}
+		
+		public string StatusText {
+			get { return statusText; }
+		}
+		
+		public bool Offline {
+			get {
+				return false;
+			}
+			set {
+			}
+		}
+		
+		internal System.ComponentModel.EventHandlerList DomEvents {
+			get {
+				if (domEvents == null)
+					domEvents = new System.ComponentModel.EventHandlerList();
+
+				return domEvents;
+			}
+		}
+
+		internal System.ComponentModel.EventHandlerList Events {
+			get {
+				if (events == null)
+					events = new System.ComponentModel.EventHandlerList();
+
+				return events;
+			}
+		}
+		
+		#region Layout
+		public void FocusIn (FocusOption focus)
+		{
+			if (!created) return;
+			Base.Focus (this, focus);
+		}
+		public void FocusOut ()
+		{
+			if (!created) return;
+			Base.Blur (this);
+		}
+		
+		public void Activate ()
+		{
+			if (!Created) return;
+			Base.Activate (this);
+		}
+		public void Deactivate ()
+		{
+			if (!created) return;
+			Base.Deactivate (this);
+		}
+
+		public void Resize (int width, int height)
+		{
+			this.width = width;
+			this.height = height;
+			isDirty = true;
+			if (!created) return;
+			Base.Resize (this, width, height);			
+		}
+
+		public void Render (byte[] data)
+		{
+			if (!Created) return;
+			if (data == null)
+				throw new ArgumentNullException ("data");
+			string html = System.Text.ASCIIEncoding.UTF8.GetString (data);
+			Render (html);
+		}
+
+		public void Render (string html)
+		{
+			if (!Created) return;
+			Render (html, "file:///", "text/html");
+		}
+
+				
+		public void Render (string html, string uri, string contentType)
+		{
+			if (!Created) return;
+			throw new Mono.WebBrowser.Exception (Mono.WebBrowser.Exception.ErrorCodes.Navigation);
+
+			IntPtr native_html = Marshal.StringToHGlobalAnsi (html);
+			Marshal.FreeHGlobal (native_html);
+
+
+		}
+		
+		public void ExecuteScript (string script) {
+			if (!Created) return;
+			Base.EvalScript (this, script);
+		}
+				
+		internal void AttachEvent (INode node, string eve, EventHandler handler) {
+			string key = String.Intern (node.GetHashCode() + ":" + eve);
+#if debug
+			Console.Error.WriteLine ("Event Attached: " + key);
+#endif
+			DomEvents.AddHandler (key, handler);
+		}
+
+		internal void DetachEvent (INode node, string eve, EventHandler handler) {
+			string key = String.Intern (node.GetHashCode() + ":" + eve);
+#if debug			
+			Console.Error.WriteLine ("Event Detached: " + key);
+#endif			
+			DomEvents.RemoveHandler (key, handler);
+		}
+		
+		#endregion
+
+		#region Events
+		internal static object KeyDownEvent = new object ();
+		internal static object KeyPressEvent = new object ();
+		internal static object KeyUpEvent = new object ();
+		internal static object MouseClickEvent = new object ();
+		internal static object MouseDoubleClickEvent = new object ();
+		internal static object MouseDownEvent = new object ();
+		internal static object MouseEnterEvent = new object ();
+		internal static object MouseLeaveEvent = new object ();
+		internal static object MouseMoveEvent = new object ();
+		internal static object MouseUpEvent = new object ();
+		internal static object FocusEvent = new object ();
+		internal static object BlurEvent = new object ();
+		internal static object CreateNewWindowEvent = new object ();
+		internal static object AlertEvent = new object ();
+			
+		internal static object LoadStartedEvent = new object ();
+		internal static object LoadCommitedEvent = new object ();
+		internal static object ProgressChangedEvent = new object ();
+		internal static object LoadFinishedEvent = new object ();	
+		
+		internal static object LoadEvent = new object ();
+		internal static object UnloadEvent = new object ();
+		internal static object StatusChangedEvent = new object ();
+		internal static object SecurityChangedEvent = new object ();
+		internal static object ProgressEvent = new object ();
+		internal static object ContextMenuEvent = new object ();
+		
+		internal static object NavigationRequestedEvent = new object ();
+		
+		public event NodeEventHandler KeyDown
+		{
+			add { Events.AddHandler (KeyDownEvent, value); }
+			remove { Events.RemoveHandler (KeyDownEvent, value); }
+		}
+
+		public event NodeEventHandler KeyPress
+		{
+			add { Events.AddHandler (KeyPressEvent, value); }
+			remove { Events.RemoveHandler (KeyPressEvent, value); }
+		}
+		public event NodeEventHandler KeyUp
+		{
+			add { Events.AddHandler (KeyUpEvent, value); }
+			remove { Events.RemoveHandler (KeyUpEvent, value); }
+		}
+		public event NodeEventHandler MouseClick
+		{
+			add { Events.AddHandler (MouseClickEvent, value); }
+			remove { Events.RemoveHandler (MouseClickEvent, value); }
+		}
+		public event NodeEventHandler MouseDoubleClick
+		{
+			add { Events.AddHandler (MouseDoubleClickEvent, value); }
+			remove { Events.RemoveHandler (MouseDoubleClickEvent, value); }
+		}
+		public event NodeEventHandler MouseDown
+		{
+			add { Events.AddHandler (MouseDownEvent, value); }
+			remove { Events.RemoveHandler (MouseDownEvent, value); }
+		}
+		public event NodeEventHandler MouseEnter
+		{
+			add { Events.AddHandler (MouseEnterEvent, value); }
+			remove { Events.RemoveHandler (MouseEnterEvent, value); }
+		}
+		public event NodeEventHandler MouseLeave
+		{
+			add { Events.AddHandler (MouseLeaveEvent, value); }
+			remove { Events.RemoveHandler (MouseLeaveEvent, value); }
+		}
+		public event NodeEventHandler MouseMove
+		{
+			add { Events.AddHandler (MouseMoveEvent, value); }
+			remove { Events.RemoveHandler (MouseMoveEvent, value); }
+		}
+		public event NodeEventHandler MouseUp
+		{
+			add { Events.AddHandler (MouseUpEvent, value); }
+			remove { Events.RemoveHandler (MouseUpEvent, value); }
+		}
+		public event EventHandler Focus
+		{
+			add { Events.AddHandler (FocusEvent, value); }
+			remove { Events.RemoveHandler (FocusEvent, value); }
+		}
+		public event EventHandler Blur
+		{
+			add { Events.AddHandler (BlurEvent, value); }
+			remove { Events.RemoveHandler (BlurEvent, value); }
+		}
+		public event CreateNewWindowEventHandler CreateNewWindow
+		{
+			add { Events.AddHandler (CreateNewWindowEvent, value); }
+			remove { Events.RemoveHandler (CreateNewWindowEvent, value); }
+		}
+		public event AlertEventHandler Alert
+		{
+			add { Events.AddHandler (AlertEvent, value); }
+			remove { Events.RemoveHandler (AlertEvent, value); }
+		}
+		public event EventHandler Loaded
+		{
+			add { Events.AddHandler (LoadEvent, value); }
+			remove { Events.RemoveHandler (LoadEvent, value); }
+		}
+		public event EventHandler Unloaded
+		{
+			add { Events.AddHandler (UnloadEvent, value); }
+			remove { Events.RemoveHandler (UnloadEvent, value); }
+		}
+
+ 		public event StatusChangedEventHandler StatusChanged
+		{
+			add { Events.AddHandler (StatusChangedEvent, value); }
+			remove { Events.RemoveHandler (StatusChangedEvent, value); }
+		}
+		
+ 		public event SecurityChangedEventHandler SecurityChanged
+		{
+			add { Events.AddHandler (SecurityChangedEvent, value); }
+			remove { Events.RemoveHandler (SecurityChangedEvent, value); }
+		}
+
+		public event LoadStartedEventHandler LoadStarted
+		{
+			add { Events.AddHandler (LoadStartedEvent, value); }
+			remove { Events.RemoveHandler (LoadStartedEvent, value); }
+		}
+		
+		public event LoadCommitedEventHandler LoadCommited
+		{
+			add { Events.AddHandler (LoadCommitedEvent, value); }
+			remove { Events.RemoveHandler (LoadCommitedEvent, value); }
+		}		
+		
+		public event ProgressChangedEventHandler ProgressChanged
+		{
+			add { Events.AddHandler (ProgressChangedEvent, value); }
+			remove { Events.RemoveHandler (ProgressChangedEvent, value); }
+		}
+		
+		public event LoadFinishedEventHandler LoadFinished
+		{
+			add { Events.AddHandler (LoadFinishedEvent, value); }
+			remove { Events.RemoveHandler (LoadFinishedEvent, value); }
+		}
+
+		public event ContextMenuEventHandler ContextMenuShown
+		{
+			add { Events.AddHandler (ContextMenuEvent, value); }
+			remove { Events.RemoveHandler (ContextMenuEvent, value); }
+		}
+
+		public event NavigationRequestedEventHandler NavigationRequested
+		{
+			add { }
+			remove { }
+		}
+
+		internal static object GenericEvent = new object ();
+		internal event EventHandler Generic
+		{
+			add { Events.AddHandler (GenericEvent, value); }
+			remove { Events.RemoveHandler (GenericEvent, value); }
+		}
+
+		#endregion
+
+
+	}
+}
--- /dev/null
+++ mono-3.2.3+dfsg/mcs/class/Mono.WebBrowser/Mono.NullBrowser/Base.cs
@@ -0,0 +1,174 @@
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// Copyright (c) 2007, 2008 Novell, Inc.
+//
+// Authors:
+//	Andreia Gaita (avidigal@novell.com)
+//
+
+using System;
+using System.Text;
+using System.Collections;
+using System.Runtime.InteropServices;
+using System.Diagnostics;
+using Mono.WebBrowser;
+
+namespace Mono.NullBrowser
+{
+	internal class Base
+	{
+		private static Hashtable boundControls;
+		private static bool initialized;
+		private static object initLock = new object ();
+		private static string monoMozDir;
+
+		private static bool isInitialized ()
+		{
+			if (!initialized)
+				return false;
+			return true;
+		}
+
+		static Base ()
+		{
+			boundControls = new Hashtable ();
+		}
+
+		public Base () { }
+
+		public static bool Init (WebBrowser control, Platform platform)
+		{
+			lock (initLock) {
+				if (!initialized) {
+				
+					initialized = true;
+				}
+			}
+			return initialized;
+		}
+
+		public static bool Bind (WebBrowser control, IntPtr handle, int width, int height)
+		{
+			if (!isInitialized ())
+				return false;
+
+			
+			return true;
+		}
+
+		public static bool Create (IWebBrowser control) {
+			if (!isInitialized ())
+				return false;
+
+			return true;
+		}
+
+		public static void Shutdown (IWebBrowser control)
+		{
+			lock (initLock) {
+				if (!initialized)
+					return;
+					
+				
+				boundControls.Remove (control);
+				if (boundControls.Count == 0) {
+					initialized = false;
+				}
+			}
+		}
+
+		// layout
+		public static void Focus (IWebBrowser control, FocusOption focus)
+		{
+			if (!isInitialized ())
+				return;
+
+		}
+
+
+		public static void Blur (IWebBrowser control)
+		{
+			if (!isInitialized ())
+				return;
+
+		}
+
+		public static void Activate (IWebBrowser control)
+		{
+			if (!isInitialized ())
+				return;
+
+		}
+
+		public static void Deactivate (IWebBrowser control)
+		{
+			if (!isInitialized ())
+				return;
+
+		}
+
+		public static void Resize (IWebBrowser control, int width, int height)
+		{
+			if (!isInitialized ())
+				return;
+
+		}
+
+		// navigation
+		public static void Home (IWebBrowser control)
+		{
+			if (!isInitialized ())
+				return;
+
+		}
+
+
+		public static IntPtr StringInit ()
+		{
+			return IntPtr.Zero;
+		}
+
+		public static void StringFinish (HandleRef str)
+		{
+		}
+
+		public static string StringGet (HandleRef str)
+		{
+			return String.Empty;
+		}
+
+		public static void StringSet (HandleRef str, string text)
+		{
+		}
+
+
+		public static object GetProxyForObject (IWebBrowser control, Guid iid, object obj)
+		{
+			return null;
+		}
+
+		public static string EvalScript (IWebBrowser control, string script)
+		{
+			return null;
+		}
+
+
+	}
+}
--- /dev/null
+++ mono-3.2.3+dfsg/mcs/class/Mono.WebBrowser/Mono.NullBrowser/DOM/Navigation.cs
@@ -0,0 +1,127 @@
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// Copyright (c) 2007, 2008 Novell, Inc.
+//
+// Authors:
+//	Andreia Gaita (avidigal@novell.com)
+//
+
+using System;
+using System.Runtime.InteropServices;
+using System.Text;
+using Mono.WebBrowser;
+using Mono.WebBrowser.DOM;
+
+namespace Mono.NullBrowser.DOM
+{
+	internal class Navigation: INavigation
+	{
+
+
+		#region INavigation Members
+
+		public bool CanGoBack {
+			get {
+				return false;
+			}
+		}
+
+		public bool CanGoForward {
+			get {
+				return false;
+			}
+		}
+
+		public bool Back ()
+		{
+			return false;
+		}
+
+		public bool Forward ()
+		{
+			return false;
+		}
+
+		public void Home ()
+		{
+		}
+
+		public void Reload ()
+		{
+		}
+
+		public void Reload (ReloadOption option)
+		{
+		}
+
+		public void Stop ()
+		{
+		}
+		
+		
+		/// <summary>
+		/// Navigate to the page in the history, by index.
+		/// </summary>
+		/// <param name="index">
+		/// A <see cref="System.Int32"/> representing an absolute index in the 
+		/// history (that is, > -1 and < history length
+		/// </param>
+		public void Go (int index)
+		{
+		}
+
+		/// <summary>
+		/// 
+		/// </summary>
+		/// <param name="index">
+		/// A <see cref="System.Int32"/> representing an index in the 
+		/// history, that can be relative or absolute depending on the relative argument
+		/// </param>
+		/// <param name="relative">
+		/// A <see cref="System.Boolean"/> indicating whether the index is relative to 
+		/// the current place in history or not (i.e., if relative = true, index can be
+		/// positive or negative, and index=-1 means load the previous page in the history.
+		/// if relative = false, index must be > -1, and index = 0 means load the first
+		/// page of the history.
+		/// </param>
+		public void Go (int index, bool relative) {
+		}
+		
+		public void Go (string url)
+		{
+		}
+
+		public void Go (string url, LoadFlags flags) 
+		{
+		}
+
+		public int HistoryCount {
+			get {
+				return 0;
+			}
+		}
+
+		#endregion
+
+		public override int GetHashCode () {
+			return 0;
+		}		
+	}
+}
--- mono-3.2.3+dfsg.orig/mcs/class/Mono.WebBrowser/Mono.WebBrowser/Manager.cs
+++ mono-3.2.3+dfsg/mcs/class/Mono.WebBrowser/Mono.WebBrowser/Manager.cs
@@ -52,8 +52,15 @@ namespace Mono.WebBrowser
 				}
 			}
 #endif
-			if (browserEngine == null || browserEngine == "mozilla")
-				return new Mono.Mozilla.WebBrowser (platform);
+			if (browserEngine == "mozilla") {
+				try {
+					return new Mono.Mozilla.WebBrowser (platform);
+				} catch {
+					browserEngine = null;
+				}
+			}
+			if (browserEngine == null)
+				return new Mono.NullBrowser.WebBrowser (platform);
 			throw new Exception (Mono.WebBrowser.Exception.ErrorCodes.EngineNotSupported, browserEngine);
 		}
 
--- mono-3.2.3+dfsg.orig/mcs/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/Engine.cs
+++ mono-3.2.3+dfsg/mcs/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/Engine.cs
@@ -553,14 +553,16 @@ namespace Microsoft.Build.BuildEngine {
 
 		public string DefaultToolsVersion {
 			get {
-				// This is used as the fall back version if the
-				// project can't find a version to use
-				// Hard-coded to 2.0, so it allows even vs2005 projects
-				// to build correctly, as they won't have a ToolsVersion
-				// set!
-				return String.IsNullOrEmpty (defaultToolsVersion)
-						? "2.0"
-						: defaultToolsVersion;
+				if (String.IsNullOrEmpty (defaultToolsVersion))
+#if NET_4_0
+					return "4.0";
+#elif NET_3_5
+					return "3.5";
+#else
+					return "2.0";
+#endif
+				
+				return defaultToolsVersion;
 			}
 			set {
 				if (Toolsets [value] == null)
--- mono-3.2.3+dfsg.orig/mcs/class/monodoc/Monodoc/providers/EcmaDoc.cs
+++ mono-3.2.3+dfsg/mcs/class/monodoc/Monodoc/providers/EcmaDoc.cs
@@ -541,10 +541,11 @@ namespace Monodoc.Providers
 				break;
 			// binary operators: overloading is possible [ECMA-335 §10.3.2]
 			default:
-				memberSignature =
-					nicename + "("
-					+ string.Join (",", member.Element ("Parameters").Elements ("Parameter").Select (p => (string)p.Attribute ("Type")))
-					+ ")";
+				if (member.Element ("Parameters") != null)
+					memberSignature =
+						nicename + "("
+						+ string.Join (",", member.Element ("Parameters").Elements ("Parameter").Select (p => (string)p.Attribute ("Type")))
+						+ ")";
 				break;
 			}
 
--- mono-3.2.3+dfsg.orig/mcs/class/corlib/System/Console.cs
+++ mono-3.2.3+dfsg/mcs/class/corlib/System/Console.cs
@@ -127,8 +127,7 @@ namespace System
 				int code_page = 0;
 				Encoding.InternalCodePage (ref code_page);
 
-				if (code_page != -1 && ((code_page & 0x0fffffff) == 3 // UTF8Encoding.UTF8_CODE_PAGE
-					|| ((code_page & 0x10000000) != 0)))
+				if (code_page == UTF8Encoding.UTF8_CODE_PAGE || ((code_page & 0x10000000) != 0))
 					inputEncoding = outputEncoding = Encoding.UTF8Unmarked;
 				else
 					inputEncoding = outputEncoding = Encoding.Default;
--- mono-3.2.3+dfsg.orig/data/mono.pc.in
+++ mono-3.2.3+dfsg/data/mono.pc.in
@@ -1,5 +1,5 @@
-prefix=${pcfiledir}/../..
-exec_prefix=${pcfiledir}/../..
+prefix=@prefix@
+exec_prefix=${prefix}
 libdir=${prefix}/@reloc_libdir@
 includedir=${prefix}/include/mono-@API_VER@
 sysconfdir=@sysconfdir@
--- mono-3.2.3+dfsg.orig/data/mono-cairo.pc.in
+++ mono-3.2.3+dfsg/data/mono-cairo.pc.in
@@ -1,5 +1,5 @@
-prefix=${pcfiledir}/../..
-exec_prefix=${pcfiledir}/../..
+prefix=@prefix@
+exec_prefix=${prefix}
 libdir=${prefix}/@reloc_libdir@
 includedir=${prefix}/include
 
--- mono-3.2.3+dfsg.orig/libgc/configure.in
+++ mono-3.2.3+dfsg/libgc/configure.in
@@ -114,6 +114,17 @@ case "$THREADS" in
 	AC_DEFINE(THREAD_LOCAL_ALLOC)
 	THREADDLLIBS="-lpthread -lrt"
 	;;
+     *-*-kfreebsd*-gnu)
+	AC_DEFINE(GC_FREEBSD_THREADS)
+	INCLUDES="$INCLUDES -pthread"
+	THREADDLLIBS=-pthread
+	AC_DEFINE(_REENTRANT)
+	if test "${enable_parallel_mark}" = yes; then
+		AC_DEFINE(PARALLEL_MARK)
+	fi
+	AC_DEFINE(THREAD_LOCAL_ALLOC)
+	AC_DEFINE(USE_COMPILER_TLS)
+	;;
       *-*-freebsd*)
 	AC_DEFINE(GC_FREEBSD_THREADS)
 	if test "x$PTHREAD_CFLAGS" != "x"; then
--- mono-3.2.3+dfsg.orig/libgc/dyn_load.c
+++ mono-3.2.3+dfsg/libgc/dyn_load.c
@@ -26,7 +26,7 @@
  * None of this is safe with dlclose and incremental collection.
  * But then not much of anything is safe in the presence of dlclose.
  */
-#if (defined(__linux__) || defined(__native_client__)) && !defined(_GNU_SOURCE)
+#if (defined(__linux__) || defined(__GLIBC__) || defined(__native_client__)) && !defined(_GNU_SOURCE)
     /* Can't test LINUX, since this must be define before other includes */
 #   define _GNU_SOURCE
 #endif
@@ -394,7 +394,7 @@ GC_bool GC_register_main_static_data()
 /* For glibc 2.2.4+.  Unfortunately, it doesn't work for older	*/
 /* versions.  Thanks to Jakub Jelinek for most of the code.	*/
 
-# if (defined(LINUX) || defined(NACL)) /* Are others OK here, too? */ \
+# if (defined(LINUX) || defined (__GLIBC__) || defined(NACL)) /* Are others OK here, too? */ \
      && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) \
          || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 2 && defined(DT_CONFIG))) 
 
--- mono-3.2.3+dfsg.orig/libgc/include/gc.h
+++ mono-3.2.3+dfsg/libgc/include/gc.h
@@ -493,7 +493,7 @@ GC_API GC_PTR GC_malloc_atomic_ignore_of
 #   define GC_RETURN_ADDR (GC_word)__return_address
 #endif
 
-#ifdef __linux__
+#if defined(__linux__) || defined(__GLIBC__)
 # include <features.h>
 # if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1 || __GLIBC__ > 2) \
      && !defined(__ia64__)
--- mono-3.2.3+dfsg.orig/libgc/include/private/gcconfig.h
+++ mono-3.2.3+dfsg/libgc/include/private/gcconfig.h
@@ -55,7 +55,7 @@
 # endif
 
 /* And one for FreeBSD: */
-# if defined(__FreeBSD__) && !defined(FREEBSD)
+# if (defined(__FreeBSD__) || defined(__FreeBSD_kernel__)) && !defined(FREEBSD)
 #    define FREEBSD
 # endif
 
@@ -1371,8 +1371,15 @@
 #	ifndef GC_FREEBSD_THREADS
 #	    define MPROTECT_VDB
 #	endif
-#      define SIG_SUSPEND SIGTSTP
-#      define SIG_THR_RESTART SIGCONT
+#       ifdef __GLIBC__
+#           define SIG_SUSPEND          (32+6)
+#           define SIG_THR_RESTART      (32+5)
+            extern int _end[];
+#           define DATAEND (_end)
+#       else
+#           define SIG_SUSPEND SIGTSTP
+#           define SIG_THR_RESTART SIGCONT
+#       endif
 #	define FREEBSD_STACKBOTTOM
 #	ifdef __ELF__
 #	    define DYNAMIC_LOADING
@@ -2143,6 +2150,28 @@
 	extern char * GC_FreeBSDGetDataStart();
 #	define DATASTART GC_FreeBSDGetDataStart(0x1000, &etext)
 #   endif
+#   ifdef FREEBSD
+#	define OS_TYPE "FREEBSD"
+#	ifndef GC_FREEBSD_THREADS
+#	    define MPROTECT_VDB
+#	endif
+#	ifdef __GLIBC__
+#	    define SIG_SUSPEND		(32+6)
+#	    define SIG_THR_RESTART	(32+5)
+	    extern int _end[];
+#	    define DATAEND (_end)
+#	else
+#	    define SIG_SUSPEND SIGUSR1
+#	    define SIG_THR_RESTART SIGUSR2
+#	endif
+#	define FREEBSD_STACKBOTTOM
+#	ifdef __ELF__
+#	    define DYNAMIC_LOADING
+#	endif
+	extern char etext[];
+	extern char * GC_FreeBSDGetDataStart();
+#	define DATASTART GC_FreeBSDGetDataStart(0x1000, &etext)
+#   endif
 #   ifdef NETBSD
 #	define OS_TYPE "NETBSD"
 #	ifdef __ELF__
@@ -2230,7 +2259,7 @@
 #   define SUNOS5SIGS
 # endif
 
-# if defined(FREEBSD) && (__FreeBSD__ >= 4)
+# if defined(FREEBSD) && ((__FreeBSD__ >= 4) || (__FreeBSD_kernel__ >= 4))
 #   define SUNOS5SIGS
 # endif
 
@@ -2293,7 +2322,7 @@
 #   define CACHE_LINE_SIZE 32	/* Wild guess	*/
 # endif
 
-# ifdef LINUX
+# if defined(LINUX) || defined(__GLIBC__)
 #   define REGISTER_LIBRARIES_EARLY
     /* We sometimes use dl_iterate_phdr, which may acquire an internal	*/
     /* lock.  This isn't safe after the world has stopped.  So we must	*/
@@ -2374,7 +2403,7 @@
 #if defined(SPARC)
 # define CAN_SAVE_CALL_ARGS
 #endif
-#if (defined(I386) || defined(X86_64)) && defined(LINUX)
+#if (defined(I386) || defined(X86_64)) && (defined(LINUX) || defined(__GLIBC__))
 	    /* SAVE_CALL_CHAIN is supported if the code is compiled to save	*/
 	    /* frame pointers by default, i.e. no -fomit-frame-pointer flag.	*/
 # define CAN_SAVE_CALL_ARGS
--- mono-3.2.3+dfsg.orig/support/syslog.c
+++ mono-3.2.3+dfsg/support/syslog.c
@@ -38,7 +38,16 @@ Mono_Posix_Syscall_closelog (void)
 int
 Mono_Posix_Syscall_syslog (int priority, const char* message)
 {
+#ifdef __GNUC__
+	#pragma GCC diagnostic push
+	#pragma GCC diagnostic ignored "-Wformat-security"
+#endif
+
 	syslog (priority, message);
+
+#ifdef __GNUC__
+	#pragma GCC diagnostic pop
+#endif
 	return 0;
 }
 
