Text file src/runtime/internal/atomic/asm_386.s
1 // Copyright 2015 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 #include "textflag.h"
6
7 // bool Cas(int32 *val, int32 old, int32 new)
8 // Atomically:
9 // if(*val == old){
10 // *val = new;
11 // return 1;
12 // }else
13 // return 0;
14 TEXT runtime∕internal∕atomic·Cas(SB), NOSPLIT, $0-13
15 MOVL ptr+0(FP), BX
16 MOVL old+4(FP), AX
17 MOVL new+8(FP), CX
18 LOCK
19 CMPXCHGL CX, 0(BX)
20 SETEQ ret+12(FP)
21 RET
22
23 TEXT runtime∕internal∕atomic·Casuintptr(SB), NOSPLIT, $0-13
24 JMP runtime∕internal∕atomic·Cas(SB)
25
26 TEXT runtime∕internal∕atomic·CasRel(SB), NOSPLIT, $0-13
27 JMP runtime∕internal∕atomic·Cas(SB)
28
29 TEXT runtime∕internal∕atomic·Loaduintptr(SB), NOSPLIT, $0-8
30 JMP runtime∕internal∕atomic·Load(SB)
31
32 TEXT runtime∕internal∕atomic·Loaduint(SB), NOSPLIT, $0-8
33 JMP runtime∕internal∕atomic·Load(SB)
34
35 TEXT runtime∕internal∕atomic·Storeuintptr(SB), NOSPLIT, $0-8
36 JMP runtime∕internal∕atomic·Store(SB)
37
38 TEXT runtime∕internal∕atomic·Xadduintptr(SB), NOSPLIT, $0-12
39 JMP runtime∕internal∕atomic·Xadd(SB)
40
41 TEXT runtime∕internal∕atomic·Loadint64(SB), NOSPLIT, $0-12
42 JMP runtime∕internal∕atomic·Load64(SB)
43
44 TEXT runtime∕internal∕atomic·Xaddint64(SB), NOSPLIT, $0-20
45 JMP runtime∕internal∕atomic·Xadd64(SB)
46
47
48 // bool runtime∕internal∕atomic·Cas64(uint64 *val, uint64 old, uint64 new)
49 // Atomically:
50 // if(*val == *old){
51 // *val = new;
52 // return 1;
53 // } else {
54 // return 0;
55 // }
56 TEXT runtime∕internal∕atomic·Cas64(SB), NOSPLIT, $0-21
57 MOVL ptr+0(FP), BP
58 TESTL $7, BP
59 JZ 2(PC)
60 MOVL 0, BP // crash with nil ptr deref
61 MOVL old_lo+4(FP), AX
62 MOVL old_hi+8(FP), DX
63 MOVL new_lo+12(FP), BX
64 MOVL new_hi+16(FP), CX
65 LOCK
66 CMPXCHG8B 0(BP)
67 SETEQ ret+20(FP)
68 RET
69
70 // bool Casp1(void **p, void *old, void *new)
71 // Atomically:
72 // if(*p == old){
73 // *p = new;
74 // return 1;
75 // }else
76 // return 0;
77 TEXT runtime∕internal∕atomic·Casp1(SB), NOSPLIT, $0-13
78 MOVL ptr+0(FP), BX
79 MOVL old+4(FP), AX
80 MOVL new+8(FP), CX
81 LOCK
82 CMPXCHGL CX, 0(BX)
83 SETEQ ret+12(FP)
84 RET
85
86 // uint32 Xadd(uint32 volatile *val, int32 delta)
87 // Atomically:
88 // *val += delta;
89 // return *val;
90 TEXT runtime∕internal∕atomic·Xadd(SB), NOSPLIT, $0-12
91 MOVL ptr+0(FP), BX
92 MOVL delta+4(FP), AX
93 MOVL AX, CX
94 LOCK
95 XADDL AX, 0(BX)
96 ADDL CX, AX
97 MOVL AX, ret+8(FP)
98 RET
99
100 TEXT runtime∕internal∕atomic·Xadd64(SB), NOSPLIT, $0-20
101 // no XADDQ so use CMPXCHG8B loop
102 MOVL ptr+0(FP), BP
103 TESTL $7, BP
104 JZ 2(PC)
105 MOVL 0, AX // crash when unaligned
106 // DI:SI = delta
107 MOVL delta_lo+4(FP), SI
108 MOVL delta_hi+8(FP), DI
109 // DX:AX = *addr
110 MOVL 0(BP), AX
111 MOVL 4(BP), DX
112 addloop:
113 // CX:BX = DX:AX (*addr) + DI:SI (delta)
114 MOVL AX, BX
115 MOVL DX, CX
116 ADDL SI, BX
117 ADCL DI, CX
118
119 // if *addr == DX:AX {
120 // *addr = CX:BX
121 // } else {
122 // DX:AX = *addr
123 // }
124 // all in one instruction
125 LOCK
126 CMPXCHG8B 0(BP)
127
128 JNZ addloop
129
130 // success
131 // return CX:BX
132 MOVL BX, ret_lo+12(FP)
133 MOVL CX, ret_hi+16(FP)
134 RET
135
136 TEXT runtime∕internal∕atomic·Xchg(SB), NOSPLIT, $0-12
137 MOVL ptr+0(FP), BX
138 MOVL new+4(FP), AX
139 XCHGL AX, 0(BX)
140 MOVL AX, ret+8(FP)
141 RET
142
143 TEXT runtime∕internal∕atomic·Xchguintptr(SB), NOSPLIT, $0-12
144 JMP runtime∕internal∕atomic·Xchg(SB)
145
146 TEXT runtime∕internal∕atomic·Xchg64(SB),NOSPLIT,$0-20
147 // no XCHGQ so use CMPXCHG8B loop
148 MOVL ptr+0(FP), BP
149 TESTL $7, BP
150 JZ 2(PC)
151 MOVL 0, AX // crash when unaligned
152 // CX:BX = new
153 MOVL new_lo+4(FP), BX
154 MOVL new_hi+8(FP), CX
155 // DX:AX = *addr
156 MOVL 0(BP), AX
157 MOVL 4(BP), DX
158 swaploop:
159 // if *addr == DX:AX
160 // *addr = CX:BX
161 // else
162 // DX:AX = *addr
163 // all in one instruction
164 LOCK
165 CMPXCHG8B 0(BP)
166 JNZ swaploop
167
168 // success
169 // return DX:AX
170 MOVL AX, ret_lo+12(FP)
171 MOVL DX, ret_hi+16(FP)
172 RET
173
174 TEXT runtime∕internal∕atomic·StorepNoWB(SB), NOSPLIT, $0-8
175 MOVL ptr+0(FP), BX
176 MOVL val+4(FP), AX
177 XCHGL AX, 0(BX)
178 RET
179
180 TEXT runtime∕internal∕atomic·Store(SB), NOSPLIT, $0-8
181 MOVL ptr+0(FP), BX
182 MOVL val+4(FP), AX
183 XCHGL AX, 0(BX)
184 RET
185
186 TEXT runtime∕internal∕atomic·StoreRel(SB), NOSPLIT, $0-8
187 JMP runtime∕internal∕atomic·Store(SB)
188
189 // uint64 atomicload64(uint64 volatile* addr);
190 TEXT runtime∕internal∕atomic·Load64(SB), NOSPLIT, $0-12
191 MOVL ptr+0(FP), AX
192 TESTL $7, AX
193 JZ 2(PC)
194 MOVL 0, AX // crash with nil ptr deref
195 MOVQ (AX), M0
196 MOVQ M0, ret+4(FP)
197 EMMS
198 RET
199
200 // void runtime∕internal∕atomic·Store64(uint64 volatile* addr, uint64 v);
201 TEXT runtime∕internal∕atomic·Store64(SB), NOSPLIT, $0-12
202 MOVL ptr+0(FP), AX
203 TESTL $7, AX
204 JZ 2(PC)
205 MOVL 0, AX // crash with nil ptr deref
206 // MOVQ and EMMS were introduced on the Pentium MMX.
207 MOVQ val+4(FP), M0
208 MOVQ M0, (AX)
209 EMMS
210 // This is essentially a no-op, but it provides required memory fencing.
211 // It can be replaced with MFENCE, but MFENCE was introduced only on the Pentium4 (SSE2).
212 XORL AX, AX
213 LOCK
214 XADDL AX, (SP)
215 RET
216
217 // void runtime∕internal∕atomic·Or8(byte volatile*, byte);
218 TEXT runtime∕internal∕atomic·Or8(SB), NOSPLIT, $0-5
219 MOVL ptr+0(FP), AX
220 MOVB val+4(FP), BX
221 LOCK
222 ORB BX, (AX)
223 RET
224
225 // void runtime∕internal∕atomic·And8(byte volatile*, byte);
226 TEXT runtime∕internal∕atomic·And8(SB), NOSPLIT, $0-5
227 MOVL ptr+0(FP), AX
228 MOVB val+4(FP), BX
229 LOCK
230 ANDB BX, (AX)
231 RET
View as plain text