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) 206