2004-10-15 Jakub Jelinek <jakub@redhat.com>
[kopensolaris-gnu/glibc.git] / sysdeps / mips / atomicity.h
1 /* Low-level functions for atomic operations. Mips version.
2    Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
19
20 #ifndef _MIPS_ATOMICITY_H
21 #define _MIPS_ATOMICITY_H    1
22
23 #include <inttypes.h>
24 #include <sgidefs.h>
25
26 static inline int
27 __attribute__ ((unused))
28 exchange_and_add (volatile uint32_t *mem, int val)
29 {
30   int result, tmp;
31
32   __asm__ __volatile__
33     ("/* Inline exchange & add */\n"
34      "1:\n\t"
35      ".set      push\n\t"
36 #if _MIPS_SIM == _MIPS_SIM_ABI32
37      ".set      mips2\n\t"
38 #endif
39      "ll        %0,%3\n\t"
40      "addu      %1,%4,%0\n\t"
41      "sc        %1,%2\n\t"
42      ".set      pop\n\t"
43      "beqz      %1,1b\n\t"
44      "/* End exchange & add */"
45      : "=&r"(result), "=&r"(tmp), "=m"(*mem)
46      : "m" (*mem), "r"(val)
47      : "memory");
48
49   return result;
50 }
51
52 static inline void
53 __attribute__ ((unused))
54 atomic_add (volatile uint32_t *mem, int val)
55 {
56   int result;
57
58   __asm__ __volatile__
59     ("/* Inline atomic add */\n"
60      "1:\n\t"
61      ".set      push\n\t"
62 #if _MIPS_SIM == _MIPS_SIM_ABI32
63      ".set      mips2\n\t"
64 #endif
65      "ll        %0,%2\n\t"
66      "addu      %0,%3,%0\n\t"
67      "sc        %0,%1\n\t"
68      ".set      pop\n\t"
69      "beqz      %0,1b\n\t"
70      "/* End atomic add */"
71      : "=&r"(result), "=m"(*mem)
72      : "m" (*mem), "r"(val)
73      : "memory");
74 }
75
76 static inline int
77 __attribute__ ((unused))
78 compare_and_swap (volatile long int *p, long int oldval, long int newval)
79 {
80   long int ret, temp;
81
82   __asm__ __volatile__
83     ("/* Inline compare & swap */\n"
84      "1:\n\t"
85      ".set      push\n\t"
86 #if _MIPS_SIM == _MIPS_SIM_ABI32
87      ".set      mips2\n\t"
88 #endif
89 #if _MIPS_SIM == _MIPS_SIM_ABI64
90      "lld       %1,%5\n\t"
91 #else
92      "ll        %1,%5\n\t"
93 #endif
94      "move      %0,$0\n\t"
95      "bne       %1,%3,2f\n\t"
96      "move      %0,%4\n\t"
97 #if _MIPS_SIM == _MIPS_SIM_ABI64
98      "scd       %0,%2\n\t"
99 #else
100      "sc        %0,%2\n\t"
101 #endif
102      ".set      pop\n\t"
103      "beqz      %0,1b\n"
104      "2:\n\t"
105      "/* End compare & swap */"
106      : "=&r" (ret), "=&r" (temp), "=m" (*p)
107      : "r" (oldval), "r" (newval), "m" (*p)
108      : "memory");
109
110   return ret;
111 }
112
113 #endif /* atomicity.h */