[kaffe] CVS kaffe (guilhem): Really update atomic on MIPS.

Kaffe CVS cvs-commits at kaffe.org
Sun Dec 25 08:49:51 PST 2005


PatchSet 7051 
Date: 2005/12/25 16:42:13
Author: guilhem
Branch: HEAD
Tag: (none) 
Log:
Really update atomic on MIPS.

Members: 
	config/mips/atomic.h:1.6->1.7 

Index: kaffe/config/mips/atomic.h
diff -u kaffe/config/mips/atomic.h:1.6 kaffe/config/mips/atomic.h:1.7
--- kaffe/config/mips/atomic.h:1.6	Sun Dec 25 16:09:47 2005
+++ kaffe/config/mips/atomic.h	Sun Dec 25 16:42:13 2005
@@ -1,10 +1,24 @@
-/* Copyright (C) 2005 Thiemo Seufer
-   Atomic functions for MIPS
+/* Low-level functions for atomic operations. Mips version.
+   Copyright (C) 2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
 
-   This file is free software; you can redistribute it and/or
+   The GNU C Library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version. */
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifndef _MIPS_BITS_ATOMIC_H
+#define _MIPS_BITS_ATOMIC_H 1
 
 #include "config-int.h"
 #include <sgidefs.h>
@@ -24,491 +38,266 @@
 typedef intmax_t atomic_max_t;
 typedef uintmax_t uatomic_max_t;
 
-/*
- * MIPS does not have byte and halfword forms of load linked and store
- * conditional. So for MIPS we stub out the 8- and 16-bit forms.
- */
-#define __arch_compare_and_exchange_bool_8_int(mem, newval, oldval, mb1, mb2)	\
-  ({ __builtin_trap (); 0; })
-
-#define __arch_compare_and_exchange_bool_16_int(mem, newval, oldval, mb1, mb2)	\
-  ({ __builtin_trap (); 0; })
-
-#define __arch_compare_and_exchange_val_8_int(mem, newval, oldval, mb1, mb2)	\
-  ({ __builtin_trap (); 0; })
-
-#define __arch_compare_and_exchange_val_16_int(mem, newval, oldval, mb1, mb2)	\
-  ({ __builtin_trap (); 0; })
-
-#ifdef UP
-# define __MB		/* nothing */
+#if _MIPS_SIM == _ABIO32
+#define MIPS_PUSH_MIPS2 ".set	mips2\n\t"
 #else
-# define __MB		"	sync\n"
-# define atomic_full_barrier()	__asm ("sync" : : : "memory");
-# define atomic_read_barrier()	__asm ("sync" : : : "memory");
-# define atomic_write_barrier()	__asm ("sync" : : : "memory");
+#define MIPS_PUSH_MIPS2
 #endif
 
-/* Compare and exchange.  For all of the "xxx" routines, we expect a
-   "__prev" and a "__cmp" variable to be provided by the enclosing scope,
-   in which values are returned.  */
-
-#define __arch_compare_and_exchange_xxx_32_int(mem, new, old, mb1, mb2) \
-({									\
-  __asm__ __volatile__ (						\
-	"	.set noreorder\n"					\
-		mb1							\
-	"1:	ll	%0,%2\n"					\
-	"	 li	%1,0\n"						\
-	"	bne	%0,%3,2f\n"					\
-	"	move	%1,%4\n"					\
-	"	sc	%1,%2\n"					\
-	"	beqz	%1,1b\n"					\
-	"	 nop\n"							\
-		mb2							\
-	"2:\n"								\
-	"	.set reorder\n"						\
-	:  "=&r" (__prev),						\
-	   "=&r" (__cmp)						\
-	: "R" (*(volatile atomic32_t *)(mem)),				\
-	   "r" ((atomic32_t)(old)),					\
-	   "r" ((atomic32_t)(new))					\
-	: "memory");							\
-})
-
-#define __arch_compare_and_exchange_xxx_64_int(mem, new, old, mb1, mb2)	\
-({									\
-  __asm__ __volatile__ (						\
-	"	.set noreorder\n"					\
-		mb1							\
-	"1:	lld	%0,%2\n"					\
-	"	 li	%1,0\n"						\
-	"	bne	%0,%3,2f\n"					\
-	"	move	%1,%4\n"					\
-	"	scd	%1,%2\n"					\
-	"	beqz	%1,1b\n"					\
-	"	 nop\n"							\
-		mb2							\
-	"2:\n"								\
-	"	.set reorder"						\
-	:  "=&r" (__prev),						\
-	   "=&r" (__cmp)						\
-	:  "R" (*(volatile atomic32_t *)(mem)),				\
-	   "r" ((atomic64_t)(old)),					\
-	   "r" ((atomic64_t)(new))					\
-	: "memory");							\
-})
-
-/* For all "bool" routines, we return FALSE if exchange successful.  */
-
-#define __arch_compare_and_exchange_bool_32_int(mem, new, old, mb1, mb2) \
-({ unsigned long __prev; int __cmp;					\
-   __arch_compare_and_exchange_xxx_32_int(mem, new, old, mb1, mb2);	\
-   !__cmp; })
-
-#if _MIPS_SIM == _MIPS_SIM_ABI32
-# define __arch_compare_and_exchange_bool_64_int(mem, new, old, mb1, mb2) \
-  ({ __builtin_trap (); 0; })
-#else
-# define __arch_compare_and_exchange_bool_64_int(mem, new, old, mb1, mb2) \
-({ unsigned long __prev; int __cmp;					\
-   __arch_compare_and_exchange_xxx_64_int(mem, new, old, mb1, mb2);	\
-   !__cmp; })
+/* See the comments in <sys/asm.h> about the use of the sync instruction.  */
+#ifndef MIPS_SYNC
+# define MIPS_SYNC	sync
 #endif
 
-/* For all "val" routines, return the old value whether exchange
-   successful or not.  */
-
-#define __arch_compare_and_exchange_val_32_int(mem, new, old, mb1, mb2) \
-({ unsigned long __prev; int __cmp;					\
-   __arch_compare_and_exchange_xxx_32_int(mem, new, old, mb1, mb2);	\
-   (typeof (*mem))__prev; })
-
-#if _MIPS_SIM == _MIPS_SIM_ABI32
-# define __arch_compare_and_exchange_val_64_int(mem, new, old, mb1, mb2) \
-  ({ __builtin_trap (); 0; })
-#else
-# define __arch_compare_and_exchange_val_64_int(mem, new, old, mb1, mb2) \
-({ unsigned long __prev; int __cmp;					\
-   __arch_compare_and_exchange_xxx_64_int(mem, new, old, mb1, mb2);	\
-   (typeof (*mem))__prev; })
-#endif
+#define MIPS_SYNC_STR_2(X) #X
+#define MIPS_SYNC_STR_1(X) MIPS_SYNC_STR_2(X)
+#define MIPS_SYNC_STR MIPS_SYNC_STR_1(MIPS_SYNC)
 
-/* Compare and exchange with "acquire" semantics, ie barrier after.  */
+/* Compare and exchange.  For all of the "xxx" routines, we expect a
+   "__prev" and a "__cmp" variable to be provided by the enclosing scope,
+   in which values are returned.  */
 
-#define atomic_compare_and_exchange_bool_acq(mem, new, old)		\
-  __atomic_bool_bysize (__arch_compare_and_exchange_bool, int,		\
-		        mem, new, old, "", __MB)
-
-#define atomic_compare_and_exchange_val_acq(mem, new, old)		\
-  __atomic_val_bysize (__arch_compare_and_exchange_val, int,		\
-		       mem, new, old, "", __MB)
+#define __arch_compare_and_exchange_xxx_8_int(mem, newval, oldval, rel, acq) \
+  (abort (), __prev = __cmp = 0)
 
-/* Compare and exchange with "release" semantics, ie barrier before.  */
+#define __arch_compare_and_exchange_xxx_16_int(mem, newval, oldval, rel, acq) \
+  (abort (), __prev = __cmp = 0)
 
-#define atomic_compare_and_exchange_bool_rel(mem, new, old)		\
-  __atomic_bool_bysize (__arch_compare_and_exchange_bool, int,		\
-		        mem, new, old, __MB, "")
-
-#define atomic_compare_and_exchange_val_rel(mem, new, old)		\
-  __atomic_val_bysize (__arch_compare_and_exchange_val, int,		\
-		       mem, new, old, __MB, "")
-
-
-/* Atomically store value and return the previous value.  */
-
-#define __arch_exchange_8_int(mem, value, mb1, mb2)			\
-  ({ __builtin_trap (); 0; })
-
-#define __arch_exchange_16_int(mem, value, mb1, mb2)			\
-  ({ __builtin_trap (); 0; })
-
-#define __arch_exchange_32_int(mem, value, mb1, mb2)			\
-({									\
-  unsigned int __ret, __tmp;						\
-  __asm__ __volatile__ (						\
-	"	.set noreorder\n"					\
-		mb1							\
-	"1:	ll	%0,%2\n"					\
-	"	move	%1,%3\n"					\
-	"	sc	%1,%2\n"					\
-	"	beqz	%1,1b\n"					\
-	"	 nop\n"							\
-		mb2							\
-	"	.set reorder\n"						\
-	: "=&r" (__ret),						\
-	  "=&r" (__tmp)							\
-	: "R" (*mem),							\
-	  "r" ((unsigned int)(value))					\
-	: "memory");							\
-  __ret; })
-
-#if _MIPS_SIM == _MIPS_SIM_ABI32
-# define __arch_exchange_64_int(mem, value, mb1, mb2)			\
-  ({ __builtin_trap (); 0; })
+#define __arch_compare_and_exchange_xxx_32_int(mem, newval, oldval, rel, acq) \
+     __asm__ __volatile__ (						      \
+     ".set	push\n\t"						      \
+     MIPS_PUSH_MIPS2							      \
+     rel	"\n"							      \
+     "1:\t"								      \
+     "ll	%0,%4\n\t"						      \
+     "move	%1,$0\n\t"						      \
+     "bne	%0,%2,2f\n\t"						      \
+     "move	%1,%3\n\t"						      \
+     "sc	%1,%4\n\t"						      \
+     "beqz	%1,1b\n"						      \
+     acq	"\n\t"							      \
+     ".set	pop\n"							      \
+     "2:\n\t"								      \
+	      : "=&r" (__prev), "=&r" (__cmp)				      \
+	      : "r" (oldval), "r" (newval), "m" (*mem)			      \
+	      : "memory")
+
+#if _MIPS_SIM == _ABIO32
+/* We can't do an atomic 64-bit operation in O32.  */
+#define __arch_compare_and_exchange_xxx_64_int(mem, newval, oldval, rel, acq) \
+  (abort (), __prev = __cmp = 0)
 #else
-# define __arch_exchange_64_int(mem, value, mb1, mb2)			\
-({									\
-  unsigned long __ret, __tmp;						\
-  __asm__ __volatile__ (						\
-	"	.set noreorder\n"					\
-		mb1							\
-	"1:	lld	%0,%2\n"					\
-	"	move	%1,%3\n"					\
-	"	scd	%1,%2\n"					\
-	"	beqz	%1,1b\n"					\
-	"	 nop\n"							\
-		mb2							\
-	"	.set reorder\n"						\
-	: "=&r" (__ret),						\
-	  "=&r" (__tmp)							\
-	: "R" (*mem),							\
-	  "r" (value)							\
-	: "memory");							\
-  __ret; })
+#define __arch_compare_and_exchange_xxx_64_int(mem, newval, oldval, rel, acq) \
+     __asm__ __volatile__ ("\n"						      \
+     ".set	push\n\t"						      \
+     MIPS_PUSH_MIPS2							      \
+     rel	"\n"							      \
+     "1:\t"								      \
+     "lld	%0,%4\n\t"						      \
+     "move	%1,$0\n\t"						      \
+     "bne	%0,%2,2f\n\t"						      \
+     "move	%1,%3\n\t"						      \
+     "scd	%1,%4\n\t"						      \
+     "beqz	%1,1b\n"						      \
+     acq	"\n\t"							      \
+     ".set	pop\n"							      \
+     "2:\n\t"								      \
+	      : "=&r" (__prev), "=&r" (__cmp)				      \
+	      : "r" (oldval), "r" (newval), "m" (*mem)			      \
+	      : "memory")
 #endif
 
-#define atomic_exchange_acq(mem, value)					\
-  __atomic_val_bysize (__arch_exchange, int, mem, value, "", __MB)
+/* For all "bool" routines, we return FALSE if exchange succesful.  */
 
-#define atomic_exchange_rel(mem, value)					\
-  __atomic_val_bysize (__arch_exchange, int, mem, value, __MB, "")
+#define __arch_compare_and_exchange_bool_8_int(mem, new, old, rel, acq)	\
+({ typeof (*mem) __prev; int __cmp;					\
+   __arch_compare_and_exchange_xxx_8_int(mem, new, old, rel, acq);	\
+   !__cmp; })
 
+#define __arch_compare_and_exchange_bool_16_int(mem, new, old, rel, acq) \
+({ typeof (*mem) __prev; int __cmp;					\
+   __arch_compare_and_exchange_xxx_16_int(mem, new, old, rel, acq);	\
+   !__cmp; })
 
-/* Atomically add value and return the previous (unincremented) value.  */
+#define __arch_compare_and_exchange_bool_32_int(mem, new, old, rel, acq) \
+({ typeof (*mem) __prev; int __cmp;					\
+   __arch_compare_and_exchange_xxx_32_int(mem, new, old, rel, acq);	\
+   !__cmp; })
 
-#define __arch_exchange_and_add_8_int(mem, value, mb1, mb2)		\
-  ({ __builtin_trap (); 0; })
+#define __arch_compare_and_exchange_bool_64_int(mem, new, old, rel, acq) \
+({ typeof (*mem) __prev; int __cmp;					\
+   __arch_compare_and_exchange_xxx_64_int(mem, new, old, rel, acq);	\
+   !__cmp; })
 
-#define __arch_exchange_and_add_16_int(mem, value, mb1, mb2)		\
-  ({ __builtin_trap (); 0; })
+/* For all "val" routines, return the old value whether exchange
+   successful or not.  */
 
-#define __arch_exchange_and_add_32_int(mem, value, mb1, mb2)		\
-({									\
-  unsigned int __ret, __tmp;						\
-  __asm__ __volatile__ (						\
-	"	.set noreorder\n"					\
-		mb1							\
-	"1:	ll	%0,%2\n"					\
-	"	addu	%1,%4,%0\n"					\
-	"	sc	%1,%2\n"					\
-	"	beqz	%1,1b\n"					\
-	"	 nop\n"							\
-		mb2							\
-	"	.set reorder\n"						\
-	: "=&r" (__ret),						\
-	  "=&r" (__tmp)							\
-	: "R" (*mem),							\
-	  "r" ((unsigned int)(value))					\
-	: "memory");							\
-  __ret; })
-
-#if _MIPS_SIM == _MIPS_SIM_ABI32
-# define __arch_exchange_and_add_64_int(mem, value, mb1, mb2)		\
-  ({ __builtin_trap (); 0; })
-#else
-# define __arch_exchange_and_add_64_int(mem, value, mb1, mb2)		\
-({									\
-  unsigned long __ret, __tmp;						\
-  __asm__ __volatile__ (						\
-	"	.set noreorder\n"					\
-		mb1							\
-	"1:	lld	%0,%2\n"					\
-	"	daddu	%1,%3,%0\n"					\
-	"	scd	%1,%2\n"					\
-	"	beqz	%1,1b\n"					\
-	"	 nop\n"							\
-		mb2							\
-	"	.set reorder\n"						\
-	: "=&r" (__ret),						\
-	  "=&r" (__tmp)							\
-	: "R" (*mem),							\
-	  "r" ((unsigned long)(value))					\
-	: "memory");							\
-  __ret; })
-#endif
+#define __arch_compare_and_exchange_val_8_int(mem, new, old, rel, acq)	\
+({ typeof (*mem) __prev; int __cmp;					\
+   __arch_compare_and_exchange_xxx_8_int(mem, new, old, rel, acq);	\
+   (typeof (*mem))__prev; })
 
-/* ??? Barrier semantics for atomic_exchange_and_add appear to be 
-   undefined.  Use full barrier for now, as that's safe.  */
-#define atomic_exchange_and_add(mem, value)				\
-  __atomic_val_bysize (__arch_exchange_and_add, int, mem, value, __MB, __MB)
+#define __arch_compare_and_exchange_val_16_int(mem, new, old, rel, acq) \
+({ typeof (*mem) __prev; int __cmp;					\
+   __arch_compare_and_exchange_xxx_16_int(mem, new, old, rel, acq);	\
+   (typeof (*mem))__prev; })
 
+#define __arch_compare_and_exchange_val_32_int(mem, new, old, rel, acq) \
+({ typeof (*mem) __prev; int __cmp;					\
+   __arch_compare_and_exchange_xxx_32_int(mem, new, old, rel, acq);	\
+   (typeof (*mem))__prev; })
 
-/* Atomically increment value (and return the incremented value).  */
+#define __arch_compare_and_exchange_val_64_int(mem, new, old, rel, acq) \
+({ typeof (*mem) __prev; int __cmp;					\
+   __arch_compare_and_exchange_xxx_64_int(mem, new, old, rel, acq);	\
+   (typeof (*mem))__prev; })
 
-#define __arch_increment_8_int(mem, mb1, mb2)				\
-  ({ __builtin_trap (); 0; })
+/* Compare and exchange with "acquire" semantics, ie barrier after.  */
 
-#define __arch_increment_16_int(mem, mb1, mb2)				\
-  ({ __builtin_trap (); 0; })
-
-#define __arch_increment_32_int(mem, mb1, mb2)				\
-({									\
-  unsigned int __ret, __tmp;						\
-  __asm__ __volatile__ (						\
-	"	.set noreorder\n"					\
-		mb1							\
-	"1:	ll	%0,%2\n"					\
-	"	addiu	%0,%1,1\n"					\
-	"	sc	%0,%2\n"					\
-	"	beqz	%0,1b\n"					\
-	"	 addiu	%0,%0,1\n"					\
-		mb2							\
-	"	.set reorder\n"						\
-	: "=&r" (__ret),						\
-	  "=&r" (__tmp)							\
-	: "R" (*mem)							\
-	: "memory");							\
-  __ret; })
-
-#if _MIPS_SIM == _MIPS_SIM_ABI32
-# define __arch_increment_64_int(mem, mb1, mb2)				\
-  ({ __builtin_trap (); 0; })
-#else
-# define __arch_increment_64_int(mem, mb1, mb2)				\
-({									\
-  unsigned long __ret, __tmp;						\
-  __asm__ __volatile__ (						\
-	"	.set noreorder\n"					\
-		mb1							\
-	"1:	lld	%0,%2\n"					\
-	"	daddiu	%1,%0,1\n"					\
-	"	scd	%1,%2\n"					\
-	"	beqz	%1,1b\n"					\
-	"	 daddiu	%0,%0,1\n"					\
-		mb2							\
-	"	.set reorder\n"						\
-	: "=&r" (__ret),						\
-	  "=&r" (__tmp)							\
-	: "R" (*mem)							\
-	: "memory");							\
-  __ret; })
-#endif
+#define atomic_compare_and_exchange_bool_acq(mem, new, old)	\
+  __atomic_bool_bysize (__arch_compare_and_exchange_bool, int,	\
+		        mem, new, old, "", MIPS_SYNC_STR)
+
+#define atomic_compare_and_exchange_val_acq(mem, new, old)	\
+  __atomic_val_bysize (__arch_compare_and_exchange_val, int,	\
+		       mem, new, old, "", MIPS_SYNC_STR)
 
-/* ??? Barrier semantics for atomic_increment_val appear to be 
-   undefined.  Use full barrier for now, as that's safe.  */
-#define atomic_increment_val(mem)					\
-  __atomic_val_bysize (__arch_increment, int, mem, __MB, __MB)
+/* Compare and exchange with "release" semantics, ie barrier before.  */
 
-#define atomic_increment(mem)						\
-  ({ __atomic_val_bysize (__arch_increment, int, mem, __MB, __MB); (void) 0; })
+#define atomic_compare_and_exchange_bool_rel(mem, new, old)	\
+  __atomic_bool_bysize (__arch_compare_and_exchange_bool, int,	\
+		        mem, new, old, MIPS_SYNC_STR, "")
+
+#define atomic_compare_and_exchange_val_rel(mem, new, old)	\
+  __atomic_val_bysize (__arch_compare_and_exchange_val, int,	\
+		       mem, new, old, MIPS_SYNC_STR, "")
 
 
-/* Atomically decrement value (and return the decremented value).  */
 
-#define __arch_decrement_8_int(mem, mb1, mb2)				\
-  ({ __builtin_trap (); 0; })
-
-#define __arch_decrement_16_int(mem, mb1, mb2)				\
-  ({ __builtin_trap (); 0; })
-
-#define __arch_decrement_32_int(mem, mb1, mb2)				\
-({									\
-  unsigned int __ret, __tmp;						\
-  __asm__ __volatile__ (						\
-	"	.set noreorder\n"					\
-		mb1							\
-	"1:	ll	%0,%2\n"					\
-	"	addiu	%1,%0,-1\n"					\
-	"	sc	%1,%2\n"					\
-	"	beqz	%1,1b\n"					\
-	"	 addiu	%0,%0,-1\n"					\
-		mb2							\
-	"	.set reorder\n"						\
-	: "=&r" (__ret),						\
-	  "=&r" (__tmp)							\
-	: "R" (*mem)							\
-	: "memory");							\
-  __ret; })
-
-#if _MIPS_SIM == _MIPS_SIM_ABI32
-# define __arch_decrement_64_int(mem, mb1, mb2)				\
-  ({ __builtin_trap (); 0; })
+/* Atomic exchange (without compare).  */
+
+#define __arch_exchange_xxx_8_int(mem, newval, rel, acq) \
+  (abort (), 0)
+
+#define __arch_exchange_xxx_16_int(mem, newval, rel, acq) \
+  (abort (), 0)
+
+#define __arch_exchange_xxx_32_int(mem, newval, rel, acq) \
+({ typeof (*mem) __prev; int __cmp;					      \
+     __asm__ __volatile__ ("\n"						      \
+     ".set	push\n\t"						      \
+     MIPS_PUSH_MIPS2							      \
+     rel	"\n"							      \
+     "1:\t"								      \
+     "ll	%0,%3\n\t"						      \
+     "move	%1,%2\n\t"						      \
+     "sc	%1,%3\n\t"						      \
+     "beqz	%1,1b\n"						      \
+     acq	"\n\t"							      \
+     ".set	pop\n"							      \
+     "2:\n\t"								      \
+	      : "=&r" (__prev), "=&r" (__cmp)				      \
+	      : "r" (newval), "m" (*mem)				      \
+	      : "memory");						      \
+  __prev; })
+
+#if _MIPS_SIM == _ABIO32
+/* We can't do an atomic 64-bit operation in O32.  */
+#define __arch_exchange_xxx_64_int(mem, newval, rel, acq) \
+  (abort (), 0)
 #else
-# define __arch_decrement_64_int(mem, mb1, mb2)				\
-({									\
-  unsigned long __ret, __tmp;						\
-  __asm__ __volatile__ (						\
-	"	.set noreorder\n"					\
-		mb1							\
-	"1:	lld	%0,%2\n"					\
-	"	daddiu	%1,%0,-1\n"					\
-	"	scd	%1,%2\n"					\
-	"	beqz	%1,1b\n"					\
-	"	 daddiu	%0,%0,-1\n"					\
-		mb2							\
-	"	.set reorder\n"						\
-	: "=&r" (__ret),						\
-	  "=&r" (__tmp)							\
-	: "R" (*mem)							\
-	: "memory");							\
-  __ret; })
+#define __arch_exchange_xxx_64_int(mem, newval, rel, acq) \
+({ typeof (*mem) __prev; int __cmp;					      \
+     __asm__ __volatile__ ("\n"						      \
+     ".set	push\n\t"						      \
+     MIPS_PUSH_MIPS2							      \
+     rel	"\n"							      \
+     "1:\n"								      \
+     "lld	%0,%3\n\t"						      \
+     "move	%1,%2\n\t"						      \
+     "scd	%1,%3\n\t"						      \
+     "beqz	%1,1b\n"						      \
+     acq	"\n\t"							      \
+     ".set	pop\n"							      \
+     "2:\n\t"								      \
+	      : "=&r" (__prev), "=&r" (__cmp)				      \
+	      : "r" (newval), "m" (*mem)				      \
+	      : "memory");						      \
+  __prev; })
 #endif
 
-/* ??? Barrier semantics for atomic_decrement_val appear to be 
-   undefined.  Use full barrier for now, as that's safe.  */
-#define atomic_decrement_val(mem)					\
-  __atomic_val_bysize (__arch_decrement, int, mem, __MB, __MB)
-
-#define atomic_decrement(mem)						\
-  ({ __atomic_val_bysize (__arch_decrement, int, mem, "", ""); (void) 0; })
-
+#define atomic_exchange_acq(mem, value) \
+  __atomic_val_bysize (__arch_exchange_xxx, int, mem, value, "", MIPS_SYNC_STR)
 
-/* Atomically decrement value and return the previous (undecremented) value.  */
+#define atomic_exchange_rel(mem, value) \
+  __atomic_val_bysize (__arch_exchange_xxx, int, mem, value, MIPS_SYNC_STR, "")
 
-#define __arch_decrement_if_positive_8_int(mem, mb1, mb2)		\
-  ({ __builtin_trap (); 0; })
-
-#define __arch_decrement_if_positive_16_int(mem, mb1, mb2)		\
-  ({ __builtin_trap (); 0; })
-
-#define __arch_decrement_if_positive_32_int(mem, mb1, mb2)		\
-({									\
-  signed int __ret, __tmp;						\
-  __asm__ __volatile__ (						\
-	"	.set noreorder\n"					\
-		mb1							\
-	"1:	ll	%0,%2\n"					\
-	"	addiu	%1,%0,-1\n"					\
-	"	bltz	%1,2f\n"					\
-	"	 nop\n"							\
-	"	sc	%1,%2\n"					\
-	"	beqz	%1,1b\n"					\
-	"	 nop\n"							\
-		mb2							\
-	"2:\n"								\
-	"	.set reorder\n"						\
-	: "=&r" (__ret),						\
-	  "=&r" (__tmp)							\
-	: "R" (*mem)							\
-	: "memory");							\
-  __ret; })
-
-#if _MIPS_SIM == _MIPS_SIM_ABI32
-# define __arch_decrement_if_positive_64_int(mem, mb1, mb2)		\
-  ({ __builtin_trap (); 0; })
-#else
-# define __arch_decrement_if_positive_64_int(mem, mb1, mb2)		\
-({									\
-  signed long __ret, __tmp;						\
-  __asm__ __volatile__ (						\
-	"	.set noreorder\n"					\
-		mb1							\
-	"1:	lld	%0,%2\n"					\
-	"	daddiu	%1,%0,-1\n"					\
-	"	bltz	%1,2f\n"					\
-	"	 nop\n"							\
-	"	scd	%1,%2\n"					\
-	"	beqz	%1,1b\n"					\
-	"	 nop\n"							\
-		mb2							\
-	"2:\n"								\
-	"	.set reorder\n"						\
-	: "=&r" (__ret),						\
-	  "=&r" (__tmp)							\
-	: "R" (*mem)							\
-	: "memory");							\
-  __ret; })
-#endif
-
-#define atomic_decrement_if_positive(mem)				\
-  __atomic_val_bysize (__arch_decrement_if_positive, int, mem, "", __MB)
 
+/* Atomically add value and return the previous (unincremented) value.  */
 
-/* Atomically set a bit and return its old value.  */
+#define __arch_exchange_and_add_8_int(mem, newval, rel, acq) \
+  (abort (), (typeof(*mem)) 0)
 
-#define __arch_bit_test_set_8_int(mem, bit, mb1, mb2)			\
-  ({ __builtin_trap (); 0; })
+#define __arch_exchange_and_add_16_int(mem, newval, rel, acq) \
+  (abort (), (typeof(*mem)) 0)
 
-#define __arch_bit_test_set_16_int(mem, bit, mb1, mb2)			\
-  ({ __builtin_trap (); 0; })
-
-#define __arch_bit_test_set_32_int(mem, bit, mb1, mb2)			\
-({									\
-  unsigned int __ret, __tmp;						\
-  __asm__ __volatile__ (						\
-	"	.set noreorder\n"					\
-		mb1							\
-	"1:	ll	%1,%2\n"					\
-	"	or	%0,%1,%3\n"					\
-	"	sc	%0,%2\n"					\
-	"	beqz	%0,1b\n"					\
-	"	 and	%0,%2,%3\n"					\
-		mb2							\
-	"2:\n"								\
-	"	.set reorder\n"						\
-	: "=&r" (__ret),						\
-	  "=&r" (__tmp)							\
-	: "R" (*mem),							\
-	  "r" (1UL << bit)						\
-	: "memory");							\
-  __ret != 0; })
-
-#if _MIPS_SIM == _MIPS_SIM_ABI32
-# define __arch_bit_test_set_64_int(mem, bit, mb1, mb2)			\
-  ({ __builtin_trap (); 0; })
+#define __arch_exchange_and_add_32_int(mem, value, rel, acq) \
+({ typeof (*mem) __prev; int __cmp;					      \
+     __asm__ __volatile__ ("\n"						      \
+     ".set	push\n\t"						      \
+     MIPS_PUSH_MIPS2							      \
+     rel	"\n"							      \
+     "1:\t"								      \
+     "ll	%0,%3\n\t"						      \
+     "addu	%1,%0,%2\n\t"						      \
+     "sc	%1,%3\n\t"						      \
+     "beqz	%1,1b\n"						      \
+     acq	"\n\t"							      \
+     ".set	pop\n"							      \
+     "2:\n\t"								      \
+	      : "=&r" (__prev), "=&r" (__cmp)				      \
+	      : "r" (value), "m" (*mem)					      \
+	      : "memory");						      \
+  __prev; })
+
+#if _MIPS_SIM == _ABIO32
+/* We can't do an atomic 64-bit operation in O32.  */
+#define __arch_exchange_and_add_64_int(mem, value, rel, acq) \
+  (abort (), (typeof(*mem)) 0)
 #else
-# define __arch_bit_test_set_64_int(mem, bit, mb1, mb2)			\
-({									\
-  unsigned long __ret, __tmp;						\
-  __asm__ __volatile__ (						\
-	"	.set noreorder\n"					\
-		mb1							\
-	"1:	lld	%1,%2\n"					\
-	"	or	%0,%1,%3\n"					\
-	"	scd	%0,%2\n"					\
-	"	beqz	%0,1b\n"					\
-	"	 and	%0,%1,%2\n"					\
-		mb2							\
-	"2:\n"								\
-	"	.set reorder\n"						\
-	: "=&r" (__ret),						\
-	  "=&r" (__tmp)							\
-	: "R" (*mem),							\
-	  "r" (1 << bit)						\
-	: "memory");							\
-  __ret; })
+#define __arch_exchange_and_add_64_int(mem, value, rel, acq) \
+({ typeof (*mem) __prev; int __cmp;					      \
+     __asm__ __volatile__ (						      \
+     ".set	push\n\t"						      \
+     MIPS_PUSH_MIPS2							      \
+     rel	"\n"							      \
+     "1:\t"								      \
+     "lld	%0,%3\n\t"						      \
+     "daddu	%1,%0,%2\n\t"						      \
+     "scd	%1,%3\n\t"						      \
+     "beqz	%1,1b\n"						      \
+     acq	"\n\t"							      \
+     ".set	pop\n"							      \
+     "2:\n\t"								      \
+	      : "=&r" (__prev), "=&r" (__cmp)				      \
+	      : "r" (value), "m" (*mem)					      \
+	      : "memory");						      \
+  __prev; })
 #endif
 
-#define atomic_bit_test_set(mem)					\
-  __atomic_val_bysize (__arch_bit_test_set, int, mem, "", __MB)
+/* ??? Barrier semantics for atomic_exchange_and_add appear to be 
+   undefined.  Use full barrier for now, as that's safe.  */
+#define atomic_exchange_and_add(mem, value) \
+  __atomic_val_bysize (__arch_exchange_and_add, int, mem, value,	      \
+		       MIPS_SYNC_STR, MIPS_SYNC_STR)
+
+/* TODO: More atomic operations could be implemented efficiently; only the
+   basic requirements are done.  */
+
+#define atomic_full_barrier() \
+  __asm__ __volatile__ (".set push\n\t"					      \
+			MIPS_PUSH_MIPS2					      \
+			MIPS_SYNC_STR "\n\t"				      \
+			".set pop" : : : "memory")
+
+#endif /* bits/atomic.h */




More information about the kaffe mailing list