~ubuntu-branches/ubuntu/quantal/libgc/quantal

« back to all changes in this revision

Viewing changes to libatomic_ops-1.2/src/atomic_ops/sysdeps/gcc/x86.h

  • Committer: Bazaar Package Importer
  • Author(s): Christoph Egger
  • Date: 2011-02-19 12:19:56 UTC
  • mfrom: (1.3.2 upstream) (0.1.5 experimental)
  • mto: This revision was merged to the branch mainline in revision 14.
  • Revision ID: james.westby@ubuntu.com-20110219121956-67rb69xlt5nud3v2
Tags: 1:7.1-5
Upload to unstable

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 
 
2
 * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.
 
3
 * Copyright (c) 1996-1999 by Silicon Graphics.  All rights reserved.
 
4
 * Copyright (c) 1999-2003 by Hewlett-Packard Company. All rights reserved.
 
5
 *
 
6
 *
 
7
 * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
 
8
 * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
 
9
 *
 
10
 * Permission is hereby granted to use or copy this program
 
11
 * for any purpose,  provided the above notices are retained on all copies.
 
12
 * Permission to modify the code and to distribute modified code is granted,
 
13
 * provided the above notices are retained, and a notice that the code was
 
14
 * modified is included with the above copyright notice.
 
15
 *
 
16
 * Some of the machine specific code was borrowed from our GC distribution.
 
17
 */
 
18
 
 
19
/* The following really assume we have a 486 or better.  Unfortunately  */
 
20
/* gcc doesn't define a suitable feature test macro based on command    */
 
21
/* line options.                                                        */
 
22
/* We should perhaps test dynamically.                                  */
 
23
 
 
24
#include "../all_aligned_atomic_load_store.h"
 
25
 
 
26
/* Real X86 implementations, except for some old WinChips, appear       */
 
27
/* to enforce ordering between memory operations, EXCEPT that a later   */
 
28
/* read can pass earlier writes, presumably due to the visible          */
 
29
/* presence of store buffers.                                           */
 
30
/* We ignore both the WinChips, and the fact that the official specs    */
 
31
/* seem to be much weaker (and arguably too weak to be usable).         */
 
32
 
 
33
#include "../ordered_except_wr.h"
 
34
 
 
35
#include "../test_and_set_t_is_char.h"
 
36
 
 
37
#include "../standard_ao_double_t.h"
 
38
 
 
39
#if defined(AO_USE_PENTIUM4_INSTRS)
 
40
AO_INLINE void
 
41
AO_nop_full()
 
42
{
 
43
  __asm__ __volatile__("mfence" : : : "memory");
 
44
}
 
45
 
 
46
#define AO_HAVE_nop_full
 
47
 
 
48
#else
 
49
 
 
50
/* We could use the cpuid instruction.  But that seems to be slower     */
 
51
/* than the default implementation based on test_and_set_full.  Thus    */
 
52
/* we omit that bit of misinformation here.                             */
 
53
 
 
54
#endif
 
55
 
 
56
/* As far as we can tell, the lfence and sfence instructions are not    */
 
57
/* currently needed or useful for cached memory accesses.               */
 
58
 
 
59
/* Really only works for 486 and later */
 
60
AO_INLINE AO_t
 
61
AO_fetch_and_add_full (volatile AO_t *p, AO_t incr)
 
62
{
 
63
  AO_t result;
 
64
 
 
65
  __asm__ __volatile__ ("lock; xaddl %0, %1" :
 
66
                        "=r" (result), "=m" (*p) : "0" (incr), "m" (*p)
 
67
                        : "memory");
 
68
  return result;
 
69
}
 
70
 
 
71
#define AO_HAVE_fetch_and_add_full
 
72
 
 
73
AO_INLINE unsigned char
 
74
AO_char_fetch_and_add_full (volatile unsigned char *p, unsigned char incr)
 
75
{
 
76
  unsigned char result;
 
77
 
 
78
  __asm__ __volatile__ ("lock; xaddb %0, %1" :
 
79
                        "=q" (result), "=m" (*p) : "0" (incr), "m" (*p)
 
80
                        : "memory");
 
81
  return result;
 
82
}
 
83
 
 
84
#define AO_HAVE_char_fetch_and_add_full
 
85
 
 
86
AO_INLINE unsigned short
 
87
AO_short_fetch_and_add_full (volatile unsigned short *p, unsigned short incr)
 
88
{
 
89
  unsigned short result;
 
90
 
 
91
  __asm__ __volatile__ ("lock; xaddw %0, %1" :
 
92
                        "=r" (result), "=m" (*p) : "0" (incr), "m" (*p)
 
93
                        : "memory");
 
94
  return result;
 
95
}
 
96
 
 
97
#define AO_HAVE_short_fetch_and_add_full
 
98
 
 
99
/* Really only works for 486 and later */
 
100
AO_INLINE void
 
101
AO_or_full (volatile AO_t *p, AO_t incr)
 
102
{
 
103
  __asm__ __volatile__ ("lock; orl %1, %0" :
 
104
                        "=m" (*p) : "r" (incr), "m" (*p) : "memory");
 
105
}
 
106
 
 
107
#define AO_HAVE_or_full
 
108
 
 
109
AO_INLINE AO_TS_VAL_t
 
110
AO_test_and_set_full(volatile AO_TS_t *addr)
 
111
{
 
112
  unsigned char oldval;
 
113
  /* Note: the "xchg" instruction does not need a "lock" prefix */
 
114
  __asm__ __volatile__("xchgb %0, %1"
 
115
                : "=q"(oldval), "=m"(*addr)
 
116
                : "0"(0xff), "m"(*addr) : "memory");
 
117
  return (AO_TS_VAL_t)oldval;
 
118
}
 
119
 
 
120
#define AO_HAVE_test_and_set_full
 
121
 
 
122
/* Returns nonzero if the comparison succeeded. */
 
123
AO_INLINE int
 
124
AO_compare_and_swap_full(volatile AO_t *addr,
 
125
                             AO_t old, AO_t new_val) 
 
126
{
 
127
  char result;
 
128
  __asm__ __volatile__("lock; cmpxchgl %3, %0; setz %1"
 
129
                       : "=m"(*addr), "=q"(result)
 
130
                       : "m"(*addr), "r" (new_val), "a"(old) : "memory");
 
131
  return (int) result;
 
132
}
 
133
 
 
134
#define AO_HAVE_compare_and_swap_full
 
135
 
 
136
/* Returns nonzero if the comparison succeeded. */
 
137
/* Really requires at least a Pentium.          */
 
138
AO_INLINE int
 
139
AO_compare_double_and_swap_double_full(volatile AO_double_t *addr,
 
140
                                       AO_t old_val1, AO_t old_val2,
 
141
                                       AO_t new_val1, AO_t new_val2) 
 
142
{
 
143
  char result;
 
144
  #if __PIC__
 
145
  /* If PIC is turned on, we can't use %ebx as it is reserved for the
 
146
     GOT poiner.  We can save and restore %ebx because GCC won't be
 
147
     using it for anything else (such as any of the m operands) */
 
148
  __asm__ __volatile__("pushl %%ebx;"   /* save ebx used for PIC GOT ptr */
 
149
                       "movl %6,%%ebx;" /* move new_val2 to %ebx */
 
150
                       "lock; cmpxchg8b %0; setz %1;"
 
151
                       "pop %%ebx;"     /* restore %ebx */
 
152
                       : "=m"(*addr), "=q"(result)
 
153
                       : "m"(*addr), "d" (old_val2), "a" (old_val1),
 
154
                         "c" (new_val2), "m" (new_val1) : "memory");
 
155
  #else
 
156
  /* We can't just do the same thing in non-PIC mode, because GCC
 
157
   * might be using %ebx as the memory operand.  We could have ifdef'd
 
158
   * in a clobber, but there's no point doing the push/pop if we don't
 
159
   * have to. */
 
160
  __asm__ __volatile__("lock; cmpxchg8b %0; setz %1;"
 
161
                       : "=m"(*addr), "=q"(result)
 
162
                       : "m"(*addr), "d" (old_val2), "a" (old_val1),
 
163
                         "c" (new_val2), "b" (new_val1) : "memory");
 
164
  #endif
 
165
  return (int) result;
 
166
}
 
167
 
 
168
#define AO_HAVE_compare_double_and_swap_double_full
 
169
 
 
170
#include "../ao_t_is_int.h"