$OpenBSD: patch-libatomic_ops-1_2_src_atomic_ops_sysdeps_gcc_mips_h,v 1.1 2008/04/01 17:41:13 kurt Exp $
--- libatomic_ops-1.2/src/atomic_ops/sysdeps/gcc/mips.h.orig	Fri Mar 21 14:01:24 2008
+++ libatomic_ops-1.2/src/atomic_ops/sysdeps/gcc/mips.h	Fri Mar 21 14:01:24 2008
@@ -0,0 +1,89 @@
+/* 
+ * Copyright (c) 2005  Thiemo Seufer <ths@networkno.de>
+ * Copyright (c) 2007  Zhang Le <r0bertz@gentoo.org>
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose,  provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ */
+
+#include "../all_aligned_atomic_load_store.h"
+#include "../test_and_set_t_is_ao_t.h"
+
+/* Data dependence does not imply read ordering.  */
+#define AO_NO_DD_ORDERING
+
+AO_INLINE void
+AO_nop_full()
+{
+  __asm__ __volatile__(
+      "       .set push           \n"
+      "       .set mips3          \n"
+      "       .set noreorder      \n"
+      "       .set nomacro        \n"
+      "       sync                \n"
+      "       .set pop              "
+      : : : "memory");
+}
+
+#define AO_HAVE_nop_full
+
+AO_INLINE int
+AO_compare_and_swap(volatile AO_t *addr, AO_t old, AO_t new_val)
+{
+  register int was_equal = 0;
+  register int temp;
+
+  __asm__ __volatile__(
+      "       .set push           \n"
+      "       .set mips3          \n"
+      "       .set noreorder      \n"
+      "       .set nomacro        \n"
+      "1:     ll      %0, %1      \n"
+      "       bne     %0, %4, 2f  \n"
+      "       move    %0, %3      \n"
+      "       sc      %0, %1      \n"
+      "       .set pop            \n"
+      "       beqz    %0, 1b      \n"
+      "       li      %2, 1       \n"
+      "2:                           "
+      : "=&r" (temp), "+R" (*addr), "+r" (was_equal)
+      : "r" (new_val), "r" (old)
+      : "memory");
+  return was_equal;
+}
+
+#define AO_HAVE_compare_and_swap
+
+AO_INLINE AO_t
+AO_fetch_and_add_full (volatile AO_t *p, AO_t incr)
+{
+  AO_t result, temp;
+  __asm__ __volatile__(
+      "       .set push           \n"
+      "       .set mips3          \n"
+      "       .set noreorder      \n"
+      "       .set nomacro        \n"
+      "1:     ll      %1, %2      \n"
+      "       addu    %0, %1, %3  \n"
+      "       sc      %0, %2      \n"
+      "       beqz    %0, 1b      \n"
+      "       addu    %0, %1, %3  \n"
+      "       sync                \n"
+      "       .set pop            \n"
+      : "=&r" (result), "=&r" (temp), "=m" (*p)
+      : "r" (incr), "m" (*p)
+      : "memory");
+  return result;
+}
+
+#define AO_HAVE_fetch_and_add_full
+
+/*
+ * FIXME: fetch_and_add_full implemented, any others?
+ */
