asm_386.s revision 0754ce079d936daf401bbf49cb69a318aa798280
1// Copyright 2011 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// +build !race
6
7#include "textflag.h"
8
9TEXT ·SwapInt32(SB),NOSPLIT,$0-12
10	JMP	·SwapUint32(SB)
11
12TEXT ·SwapUint32(SB),NOSPLIT,$0-12
13	MOVL	addr+0(FP), BP
14	MOVL	new+4(FP), AX
15	XCHGL	AX, 0(BP)
16	MOVL	AX, old+8(FP)
17	RET
18
19TEXT ·SwapInt64(SB),NOSPLIT,$0-20
20	JMP	·SwapUint64(SB)
21
22TEXT ·SwapUint64(SB),NOSPLIT,$0-20
23	// no XCHGQ so use CMPXCHG8B loop
24	MOVL	addr+0(FP), BP
25	TESTL	$7, BP
26	JZ	2(PC)
27	MOVL	0, AX // crash with nil ptr deref
28	// CX:BX = new
29	MOVL	new_lo+4(FP), BX
30	MOVL	new_hi+8(FP), CX
31	// DX:AX = *addr
32	MOVL	0(BP), AX
33	MOVL	4(BP), DX
34swaploop:
35	// if *addr == DX:AX
36	//	*addr = CX:BX
37	// else
38	//	DX:AX = *addr
39	// all in one instruction
40	LOCK
41	CMPXCHG8B	0(BP)
42	JNZ	swaploop
43
44	// success
45	// return DX:AX
46	MOVL	AX, old_lo+12(FP)
47	MOVL	DX, old_hi+16(FP)
48	RET
49
50TEXT ·SwapUintptr(SB),NOSPLIT,$0-12
51	JMP	·SwapUint32(SB)
52
53TEXT ·CompareAndSwapInt32(SB),NOSPLIT,$0-13
54	JMP	·CompareAndSwapUint32(SB)
55
56TEXT ·CompareAndSwapUint32(SB),NOSPLIT,$0-13
57	MOVL	addr+0(FP), BP
58	MOVL	old+4(FP), AX
59	MOVL	new+8(FP), CX
60	// CMPXCHGL was introduced on the 486.
61	LOCK
62	CMPXCHGL	CX, 0(BP)
63	SETEQ	swapped+12(FP)
64	RET
65
66TEXT ·CompareAndSwapUintptr(SB),NOSPLIT,$0-13
67	JMP	·CompareAndSwapUint32(SB)
68
69TEXT ·CompareAndSwapInt64(SB),NOSPLIT,$0-21
70	JMP	·CompareAndSwapUint64(SB)
71
72TEXT ·CompareAndSwapUint64(SB),NOSPLIT,$0-21
73	MOVL	addr+0(FP), BP
74	TESTL	$7, BP
75	JZ	2(PC)
76	MOVL	0, AX // crash with nil ptr deref
77	MOVL	old_lo+4(FP), AX
78	MOVL	old_hi+8(FP), DX
79	MOVL	new_lo+12(FP), BX
80	MOVL	new_hi+16(FP), CX
81	// CMPXCHG8B was introduced on the Pentium.
82	LOCK
83	CMPXCHG8B	0(BP)
84	SETEQ	swapped+20(FP)
85	RET
86
87TEXT ·AddInt32(SB),NOSPLIT,$0-12
88	JMP	·AddUint32(SB)
89
90TEXT ·AddUint32(SB),NOSPLIT,$0-12
91	MOVL	addr+0(FP), BP
92	MOVL	delta+4(FP), AX
93	MOVL	AX, CX
94	// XADD was introduced on the 486.
95	LOCK
96	XADDL	AX, 0(BP)
97	ADDL	AX, CX
98	MOVL	CX, new+8(FP)
99	RET
100
101TEXT ·AddUintptr(SB),NOSPLIT,$0-12
102	JMP	·AddUint32(SB)
103
104TEXT ·AddInt64(SB),NOSPLIT,$0-20
105	JMP	·AddUint64(SB)
106
107TEXT ·AddUint64(SB),NOSPLIT,$0-20
108	// no XADDQ so use CMPXCHG8B loop
109	MOVL	addr+0(FP), BP
110	TESTL	$7, BP
111	JZ	2(PC)
112	MOVL	0, AX // crash with nil ptr deref
113	// DI:SI = delta
114	MOVL	delta_lo+4(FP), SI
115	MOVL	delta_hi+8(FP), DI
116	// DX:AX = *addr
117	MOVL	0(BP), AX
118	MOVL	4(BP), DX
119addloop:
120	// CX:BX = DX:AX (*addr) + DI:SI (delta)
121	MOVL	AX, BX
122	MOVL	DX, CX
123	ADDL	SI, BX
124	ADCL	DI, CX
125
126	// if *addr == DX:AX {
127	//	*addr = CX:BX
128	// } else {
129	//	DX:AX = *addr
130	// }
131	// all in one instruction
132	LOCK
133	CMPXCHG8B	0(BP)
134
135	JNZ	addloop
136
137	// success
138	// return CX:BX
139	MOVL	BX, new_lo+12(FP)
140	MOVL	CX, new_hi+16(FP)
141	RET
142
143TEXT ·LoadInt32(SB),NOSPLIT,$0-8
144	JMP	·LoadUint32(SB)
145
146TEXT ·LoadUint32(SB),NOSPLIT,$0-8
147	MOVL	addr+0(FP), AX
148	MOVL	0(AX), AX
149	MOVL	AX, val+4(FP)
150	RET
151
152TEXT ·LoadInt64(SB),NOSPLIT,$0-12
153	JMP	·LoadUint64(SB)
154
155TEXT ·LoadUint64(SB),NOSPLIT,$0-12
156	MOVL	addr+0(FP), AX
157	TESTL	$7, AX
158	JZ	2(PC)
159	MOVL	0, AX // crash with nil ptr deref
160	// MOVQ and EMMS were introduced on the Pentium MMX.
161	// MOVQ (%EAX), %MM0
162	BYTE $0x0f; BYTE $0x6f; BYTE $0x00
163	// MOVQ %MM0, 0x8(%ESP)
164	BYTE $0x0f; BYTE $0x7f; BYTE $0x44; BYTE $0x24; BYTE $0x08
165	EMMS
166	RET
167
168TEXT ·LoadUintptr(SB),NOSPLIT,$0-8
169	JMP	·LoadUint32(SB)
170
171TEXT ·LoadPointer(SB),NOSPLIT,$0-8
172	JMP	·LoadUint32(SB)
173
174TEXT ·StoreInt32(SB),NOSPLIT,$0-8
175	JMP	·StoreUint32(SB)
176
177TEXT ·StoreUint32(SB),NOSPLIT,$0-8
178	MOVL	addr+0(FP), BP
179	MOVL	val+4(FP), AX
180	XCHGL	AX, 0(BP)
181	RET
182
183TEXT ·StoreInt64(SB),NOSPLIT,$0-12
184	JMP	·StoreUint64(SB)
185
186TEXT ·StoreUint64(SB),NOSPLIT,$0-12
187	MOVL	addr+0(FP), AX
188	TESTL	$7, AX
189	JZ	2(PC)
190	MOVL	0, AX // crash with nil ptr deref
191	// MOVQ and EMMS were introduced on the Pentium MMX.
192	// MOVQ 0x8(%ESP), %MM0
193	BYTE $0x0f; BYTE $0x6f; BYTE $0x44; BYTE $0x24; BYTE $0x08
194	// MOVQ %MM0, (%EAX)
195	BYTE $0x0f; BYTE $0x7f; BYTE $0x00
196	EMMS
197	// This is essentially a no-op, but it provides required memory fencing.
198	// It can be replaced with MFENCE, but MFENCE was introduced only on the Pentium4 (SSE2).
199	XORL	AX, AX
200	LOCK
201	XADDL	AX, (SP)
202	RET
203
204TEXT ·StoreUintptr(SB),NOSPLIT,$0-8
205	JMP	·StoreUint32(SB)
206