Home | History | Annotate | Download | only in atomic
      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