nsprpub/pr/src/md/unix/os_SunOS_ultrasparc.s

branch
TOR_BUG_3246
changeset 5
4ab42b5ab56c
equal deleted inserted replaced
-1:000000000000 0:20e308c00c10
1 ! -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 !
3 ! This Source Code Form is subject to the terms of the Mozilla Public
4 ! License, v. 2.0. If a copy of the MPL was not distributed with this
5 ! file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7 !
8 ! atomic increment, decrement and swap routines for V8+ sparc (ultrasparc)
9 ! using CAS (compare-and-swap) atomic instructions
10 !
11 ! this MUST be compiled with an ultrasparc-aware assembler
12 !
13 ! standard asm linkage macros; this module must be compiled
14 ! with the -P option (use C preprocessor)
15
16 #include <sys/asm_linkage.h>
17
18 ! ======================================================================
19 !
20 ! Perform the sequence a = a + 1 atomically with respect to other
21 ! fetch-and-adds to location a in a wait-free fashion.
22 !
23 ! usage : val = PR_AtomicIncrement(address)
24 ! return: current value (you'd think this would be old val)
25 !
26 ! -----------------------
27 ! Note on REGISTER USAGE:
28 ! as this is a LEAF procedure, a new stack frame is not created;
29 ! we use the caller's stack frame so what would normally be %i (input)
30 ! registers are actually %o (output registers). Also, we must not
31 ! overwrite the contents of %l (local) registers as they are not
32 ! assumed to be volatile during calls.
33 !
34 ! So, the registers used are:
35 ! %o0 [input] - the address of the value to increment
36 ! %o1 [local] - work register
37 ! %o2 [local] - work register
38 ! %o3 [local] - work register
39 ! -----------------------
40
41 ENTRY(PR_AtomicIncrement) ! standard assembler/ELF prologue
42
43 retryAI:
44 ld [%o0], %o2 ! set o2 to the current value
45 add %o2, 0x1, %o3 ! calc the new value
46 mov %o3, %o1 ! save the return value
47 cas [%o0], %o2, %o3 ! atomically set if o0 hasn't changed
48 cmp %o2, %o3 ! see if we set the value
49 bne retryAI ! if not, try again
50 nop ! empty out the branch pipeline
51 retl ! return back to the caller
52 mov %o1, %o0 ! set the return code to the new value
53
54 SET_SIZE(PR_AtomicIncrement) ! standard assembler/ELF epilogue
55
56 !
57 ! end
58 !
59 ! ======================================================================
60 !
61
62 ! ======================================================================
63 !
64 ! Perform the sequence a = a - 1 atomically with respect to other
65 ! fetch-and-decs to location a in a wait-free fashion.
66 !
67 ! usage : val = PR_AtomicDecrement(address)
68 ! return: current value (you'd think this would be old val)
69 !
70 ! -----------------------
71 ! Note on REGISTER USAGE:
72 ! as this is a LEAF procedure, a new stack frame is not created;
73 ! we use the caller's stack frame so what would normally be %i (input)
74 ! registers are actually %o (output registers). Also, we must not
75 ! overwrite the contents of %l (local) registers as they are not
76 ! assumed to be volatile during calls.
77 !
78 ! So, the registers used are:
79 ! %o0 [input] - the address of the value to increment
80 ! %o1 [local] - work register
81 ! %o2 [local] - work register
82 ! %o3 [local] - work register
83 ! -----------------------
84
85 ENTRY(PR_AtomicDecrement) ! standard assembler/ELF prologue
86
87 retryAD:
88 ld [%o0], %o2 ! set o2 to the current value
89 sub %o2, 0x1, %o3 ! calc the new value
90 mov %o3, %o1 ! save the return value
91 cas [%o0], %o2, %o3 ! atomically set if o0 hasn't changed
92 cmp %o2, %o3 ! see if we set the value
93 bne retryAD ! if not, try again
94 nop ! empty out the branch pipeline
95 retl ! return back to the caller
96 mov %o1, %o0 ! set the return code to the new value
97
98 SET_SIZE(PR_AtomicDecrement) ! standard assembler/ELF epilogue
99
100 !
101 ! end
102 !
103 ! ======================================================================
104 !
105
106 ! ======================================================================
107 !
108 ! Perform the sequence a = b atomically with respect to other
109 ! fetch-and-stores to location a in a wait-free fashion.
110 !
111 ! usage : old_val = PR_AtomicSet(address, newval)
112 !
113 ! -----------------------
114 ! Note on REGISTER USAGE:
115 ! as this is a LEAF procedure, a new stack frame is not created;
116 ! we use the caller's stack frame so what would normally be %i (input)
117 ! registers are actually %o (output registers). Also, we must not
118 ! overwrite the contents of %l (local) registers as they are not
119 ! assumed to be volatile during calls.
120 !
121 ! So, the registers used are:
122 ! %o0 [input] - the address of the value to increment
123 ! %o1 [input] - the new value to set for [%o0]
124 ! %o2 [local] - work register
125 ! %o3 [local] - work register
126 ! -----------------------
127
128 ENTRY(PR_AtomicSet) ! standard assembler/ELF prologue
129
130 retryAS:
131 ld [%o0], %o2 ! set o2 to the current value
132 mov %o1, %o3 ! set up the new value
133 cas [%o0], %o2, %o3 ! atomically set if o0 hasn't changed
134 cmp %o2, %o3 ! see if we set the value
135 bne retryAS ! if not, try again
136 nop ! empty out the branch pipeline
137 retl ! return back to the caller
138 mov %o3, %o0 ! set the return code to the prev value
139
140 SET_SIZE(PR_AtomicSet) ! standard assembler/ELF epilogue
141
142 !
143 ! end
144 !
145 ! ======================================================================
146 !
147
148 ! ======================================================================
149 !
150 ! Perform the sequence a = a + b atomically with respect to other
151 ! fetch-and-adds to location a in a wait-free fashion.
152 !
153 ! usage : newval = PR_AtomicAdd(address, val)
154 ! return: the value after addition
155 !
156 ENTRY(PR_AtomicAdd) ! standard assembler/ELF prologue
157
158 retryAA:
159 ld [%o0], %o2 ! set o2 to the current value
160 add %o2, %o1, %o3 ! calc the new value
161 mov %o3, %o4 ! save the return value
162 cas [%o0], %o2, %o3 ! atomically set if o0 hasn't changed
163 cmp %o2, %o3 ! see if we set the value
164 bne retryAA ! if not, try again
165 nop ! empty out the branch pipeline
166 retl ! return back to the caller
167 mov %o4, %o0 ! set the return code to the new value
168
169 SET_SIZE(PR_AtomicAdd) ! standard assembler/ELF epilogue
170
171 !
172 ! end
173 !

mercurial