github.com/panjjo/go@v0.0.0-20161104043856-d62b31386338/src/sync/atomic/asm_386.s (about) 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 9 TEXT ·SwapInt32(SB),NOSPLIT,$0-12 10 JMP ·SwapUint32(SB) 11 12 TEXT ·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 19 TEXT ·SwapInt64(SB),NOSPLIT,$0-20 20 JMP ·SwapUint64(SB) 21 22 TEXT ·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 34 swaploop: 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 50 TEXT ·SwapUintptr(SB),NOSPLIT,$0-12 51 JMP ·SwapUint32(SB) 52 53 TEXT ·CompareAndSwapInt32(SB),NOSPLIT,$0-13 54 JMP ·CompareAndSwapUint32(SB) 55 56 TEXT ·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 66 TEXT ·CompareAndSwapUintptr(SB),NOSPLIT,$0-13 67 JMP ·CompareAndSwapUint32(SB) 68 69 TEXT ·CompareAndSwapInt64(SB),NOSPLIT,$0-21 70 JMP ·CompareAndSwapUint64(SB) 71 72 TEXT ·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 87 TEXT ·AddInt32(SB),NOSPLIT,$0-12 88 JMP ·AddUint32(SB) 89 90 TEXT ·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 101 TEXT ·AddUintptr(SB),NOSPLIT,$0-12 102 JMP ·AddUint32(SB) 103 104 TEXT ·AddInt64(SB),NOSPLIT,$0-20 105 JMP ·AddUint64(SB) 106 107 TEXT ·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 119 addloop: 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 143 TEXT ·LoadInt32(SB),NOSPLIT,$0-8 144 JMP ·LoadUint32(SB) 145 146 TEXT ·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 152 TEXT ·LoadInt64(SB),NOSPLIT,$0-12 153 JMP ·LoadUint64(SB) 154 155 TEXT ·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 168 TEXT ·LoadUintptr(SB),NOSPLIT,$0-8 169 JMP ·LoadUint32(SB) 170 171 TEXT ·LoadPointer(SB),NOSPLIT,$0-8 172 JMP ·LoadUint32(SB) 173 174 TEXT ·StoreInt32(SB),NOSPLIT,$0-8 175 JMP ·StoreUint32(SB) 176 177 TEXT ·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 183 TEXT ·StoreInt64(SB),NOSPLIT,$0-12 184 JMP ·StoreUint64(SB) 185 186 TEXT ·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 204 TEXT ·StoreUintptr(SB),NOSPLIT,$0-8 205 JMP ·StoreUint32(SB)