903 lines
17 KiB
V
903 lines
17 KiB
V
module atomics
|
|
|
|
// add_i32 atomically adds delta to the value at dest and returns the new value.
|
|
// The operation is performed with sequential consistency.
|
|
// Panics if dest is not 4-byte aligned.
|
|
pub fn add_i32(dest &i32, delta i32) i32 {
|
|
mut result := i32(0)
|
|
asm volatile i386 {
|
|
mov edx, dest
|
|
test edx, 3
|
|
jz '1f'
|
|
call panicUnaligned
|
|
jmp '2f'
|
|
1:
|
|
mov eax, delta
|
|
lock xadd [edx], eax
|
|
add eax, delta
|
|
mov result, eax
|
|
2:
|
|
; =r (result)
|
|
; r (dest)
|
|
r (delta)
|
|
; eax
|
|
edx
|
|
memory
|
|
}
|
|
return result
|
|
}
|
|
|
|
// swap_i32 atomically stores new value at dest and returns the old value.
|
|
// The operation is performed with sequential consistency.
|
|
// Panics if dest is not 4-byte aligned.
|
|
pub fn swap_i32(dest &i32, new i32) i32 {
|
|
mut old := i32(0)
|
|
asm volatile i386 {
|
|
mov edx, dest
|
|
test edx, 3
|
|
jz '1f'
|
|
call panicUnaligned
|
|
jmp '2f'
|
|
1:
|
|
mov eax, new
|
|
xchg [edx], eax
|
|
mov old, eax
|
|
2:
|
|
; =m (old)
|
|
; r (dest)
|
|
r (new)
|
|
; eax
|
|
edx
|
|
memory
|
|
}
|
|
return old
|
|
}
|
|
|
|
// store_i32 atomically stores value at dest.
|
|
// The operation is performed with sequential consistency.
|
|
// Panics if dest is not 4-byte aligned.
|
|
pub fn store_i32(dest &i32, value i32) {
|
|
asm volatile i386 {
|
|
mov edx, dest
|
|
test edx, 3
|
|
jz '1f'
|
|
call panicUnaligned
|
|
jmp '2f'
|
|
1:
|
|
mov eax, value
|
|
xchg eax, [edx]
|
|
2:
|
|
; ; r (dest)
|
|
r (value)
|
|
; eax
|
|
edx
|
|
memory
|
|
}
|
|
}
|
|
|
|
// load_i32 atomically loads and returns the value at num.
|
|
// The operation is performed with sequential consistency.
|
|
// Panics if num is not 4-byte aligned.
|
|
pub fn load_i32(num &i32) i32 {
|
|
mut out := i32(0)
|
|
asm volatile i386 {
|
|
mov edx, num
|
|
test edx, 3
|
|
jz '1f'
|
|
call panicUnaligned
|
|
jmp '2f'
|
|
1:
|
|
mov eax, [edx]
|
|
mov out, eax
|
|
2:
|
|
; =r (out)
|
|
; r (num)
|
|
; eax
|
|
edx
|
|
memory
|
|
}
|
|
return out
|
|
}
|
|
|
|
// cas_i32 performs a compare-and-swap operation.
|
|
// If the current value at addr equals old, it atomically stores new.
|
|
// Returns true if the swap was performed, false otherwise.
|
|
// The operation is performed with sequential consistency.
|
|
// Panics if addr is not 4-byte aligned.
|
|
pub fn cas_i32(addr &i32, old i32, new i32) bool {
|
|
mut swapped := false
|
|
asm volatile i386 {
|
|
mov edx, addr
|
|
test edx, 3
|
|
jz '1f'
|
|
call panicUnaligned
|
|
jmp '2f'
|
|
1:
|
|
mov eax, old
|
|
mov ecx, new
|
|
lock cmpxchg [edx], ecx
|
|
sete al
|
|
mov swapped, al
|
|
2:
|
|
; =m (swapped)
|
|
; r (addr)
|
|
r (old)
|
|
r (new)
|
|
; eax
|
|
ecx
|
|
edx
|
|
memory
|
|
}
|
|
return swapped
|
|
}
|
|
|
|
// store_i64 atomically stores value at dest using MMX instructions.
|
|
// The operation is performed with sequential consistency.
|
|
// Requires MMX support. Panics if dest is not 8-byte aligned.
|
|
pub fn store_i64(dest &i64, value i64) {
|
|
asm volatile i386 {
|
|
mov esi, dest
|
|
test esi, 7
|
|
jz '1f'
|
|
call panicUnaligned
|
|
jmp '2f'
|
|
1:
|
|
movq mm0, value
|
|
movq [esi], mm0
|
|
emms
|
|
xor eax, eax
|
|
lock xaddl [esp], eax
|
|
2:
|
|
; ; r (dest)
|
|
m (value)
|
|
; esi
|
|
eax
|
|
mm0
|
|
memory
|
|
}
|
|
}
|
|
|
|
// load_i64 atomically loads and returns the value at num using MMX instructions.
|
|
// The operation is performed with sequential consistency.
|
|
// Requires MMX support. Panics if num is not 8-byte aligned.
|
|
pub fn load_i64(num &i64) i64 {
|
|
mut out := i64(0)
|
|
asm volatile i386 {
|
|
mov esi, num
|
|
test esi, 7
|
|
jz '1f'
|
|
call panicUnaligned
|
|
jmp '2f'
|
|
1:
|
|
movq mm0, [esi]
|
|
movq out, mm0
|
|
emms
|
|
2:
|
|
; =m (out)
|
|
; r (num)
|
|
; esi
|
|
mm0
|
|
memory
|
|
}
|
|
return out
|
|
}
|
|
|
|
// add_i64 atomically adds delta to the value at dest and returns the new value.
|
|
// Uses a compare-and-swap loop. The operation is performed with sequential consistency.
|
|
// Panics if dest is not 8-byte aligned.
|
|
pub fn add_i64(dest &i64, delta i64) i64 {
|
|
mut delta_lo := u32(u64(delta) & 0xFFFF_FFFF)
|
|
mut delta_hi := u32(u64(delta) >> 32)
|
|
mut res_lo := u32(0)
|
|
mut res_hi := u32(0)
|
|
asm volatile i386 {
|
|
mov esi, dest
|
|
test esi, 7
|
|
jz '1f'
|
|
call panicUnaligned
|
|
jmp '2f'
|
|
1:
|
|
3:
|
|
mov eax, [esi]
|
|
mov edx, [esi + 4]
|
|
mov ebx, eax
|
|
mov ecx, edx
|
|
add ebx, delta_lo
|
|
adc ecx, delta_hi
|
|
lock cmpxchg8b [esi]
|
|
jnz '3b'
|
|
mov res_lo, ebx
|
|
mov res_hi, ecx
|
|
2:
|
|
; ; r (dest)
|
|
m (delta_lo)
|
|
m (delta_hi)
|
|
m (res_lo)
|
|
m (res_hi)
|
|
; eax
|
|
ebx
|
|
ecx
|
|
edx
|
|
esi
|
|
memory
|
|
}
|
|
return i64(u64(res_lo) | (u64(res_hi) << 32))
|
|
}
|
|
|
|
// swap_i64 atomically stores value at dest and returns the old value.
|
|
// Uses a compare-and-swap loop. The operation is performed with sequential consistency.
|
|
// Panics if dest is not 8-byte aligned.
|
|
pub fn swap_i64(dest &i64, value i64) i64 {
|
|
mut value_lo := u32(u64(value) & 0xFFFF_FFFF)
|
|
mut value_hi := u32(u64(value) >> 32)
|
|
asm volatile i386 {
|
|
mov esi, dest
|
|
test esi, 7
|
|
jz '1f'
|
|
call panicUnaligned
|
|
jmp '2f'
|
|
1:
|
|
3:
|
|
mov eax, [esi]
|
|
mov edx, [esi + 4]
|
|
mov ebx, value_lo
|
|
mov ecx, value_hi
|
|
lock cmpxchg8b [esi]
|
|
jnz '3b'
|
|
mov value_lo, eax
|
|
mov value_hi, edx
|
|
2:
|
|
; ; r (dest)
|
|
m (value_lo)
|
|
m (value_hi)
|
|
; eax
|
|
ebx
|
|
ecx
|
|
edx
|
|
esi
|
|
memory
|
|
}
|
|
return i64(u64(value_lo) | (u64(value_hi) << 32))
|
|
}
|
|
|
|
// cas_i64 performs a compare-and-swap operation.
|
|
// If the current value at addr equals old, it atomically stores new.
|
|
// Returns true if the swap was performed, false otherwise.
|
|
// The operation is performed with sequential consistency.
|
|
// Panics if addr is not 8-byte aligned.
|
|
pub fn cas_i64(addr &i64, old i64, new i64) bool {
|
|
mut swapped := false
|
|
mut old_lo := u32(u64(old) & 0xFFFF_FFFF)
|
|
mut old_hi := u32(u64(old) >> 32)
|
|
mut new_lo := u32(u64(new) & 0xFFFF_FFFF)
|
|
mut new_hi := u32(u64(new) >> 32)
|
|
asm volatile i386 {
|
|
mov esi, addr
|
|
test esi, 7
|
|
jz '1f'
|
|
call panicUnaligned
|
|
jmp '2f'
|
|
1:
|
|
mov eax, old_lo
|
|
mov edx, old_hi
|
|
mov ebx, new_lo
|
|
mov ecx, new_hi
|
|
lock cmpxchg8b [esi]
|
|
sete al
|
|
mov swapped, al
|
|
2:
|
|
; =m (swapped)
|
|
; r (addr)
|
|
m (old_lo)
|
|
m (old_hi)
|
|
m (new_lo)
|
|
m (new_hi)
|
|
; eax
|
|
ebx
|
|
ecx
|
|
edx
|
|
esi
|
|
memory
|
|
}
|
|
return swapped
|
|
}
|
|
|
|
// add_u32 atomically adds delta to the value at dest and returns the new value.
|
|
// The operation is performed with sequential consistency.
|
|
// Panics if dest is not 4-byte aligned.
|
|
pub fn add_u32(dest &u32, delta u32) u32 {
|
|
mut result := u32(0)
|
|
asm volatile i386 {
|
|
mov edx, dest
|
|
test edx, 3
|
|
jz '1f'
|
|
call panicUnaligned
|
|
jmp '2f'
|
|
1:
|
|
mov eax, delta
|
|
lock xadd [edx], eax
|
|
add eax, delta
|
|
mov result, eax
|
|
2:
|
|
; =r (result)
|
|
; r (dest)
|
|
r (delta)
|
|
; eax
|
|
edx
|
|
memory
|
|
}
|
|
return result
|
|
}
|
|
|
|
// swap_u32 atomically stores new value at dest and returns the old value.
|
|
// The operation is performed with sequential consistency.
|
|
// Panics if dest is not 4-byte aligned.
|
|
pub fn swap_u32(dest &u32, new u32) u32 {
|
|
mut old := u32(0)
|
|
asm volatile i386 {
|
|
mov edx, dest
|
|
test edx, 3
|
|
jz '1f'
|
|
call panicUnaligned
|
|
jmp '2f'
|
|
1:
|
|
mov eax, new
|
|
xchg [edx], eax
|
|
mov old, eax
|
|
2:
|
|
; =m (old)
|
|
; r (dest)
|
|
r (new)
|
|
; eax
|
|
edx
|
|
memory
|
|
}
|
|
return old
|
|
}
|
|
|
|
// store_u32 atomically stores value at dest.
|
|
// The operation is performed with sequential consistency.
|
|
// Panics if dest is not 4-byte aligned.
|
|
pub fn store_u32(dest &u32, value u32) {
|
|
asm volatile i386 {
|
|
mov edx, dest
|
|
test edx, 3
|
|
jz '1f'
|
|
call panicUnaligned
|
|
jmp '2f'
|
|
1:
|
|
mov eax, value
|
|
xchg eax, [edx]
|
|
2:
|
|
; ; r (dest)
|
|
r (value)
|
|
; eax
|
|
edx
|
|
memory
|
|
}
|
|
}
|
|
|
|
// load_u32 atomically loads and returns the value at num.
|
|
// The operation is performed with sequential consistency.
|
|
// Panics if num is not 4-byte aligned.
|
|
pub fn load_u32(num &u32) u32 {
|
|
mut out := u32(0)
|
|
asm volatile i386 {
|
|
mov edx, num
|
|
test edx, 3
|
|
jz '1f'
|
|
call panicUnaligned
|
|
jmp '2f'
|
|
1:
|
|
mov eax, [edx]
|
|
mov out, eax
|
|
2:
|
|
; =r (out)
|
|
; r (num)
|
|
; eax
|
|
edx
|
|
memory
|
|
}
|
|
return out
|
|
}
|
|
|
|
// cas_u32 performs a compare-and-swap operation.
|
|
// If the current value at addr equals old, it atomically stores new.
|
|
// Returns true if the swap was performed, false otherwise.
|
|
// The operation is performed with sequential consistency.
|
|
// Panics if addr is not 4-byte aligned.
|
|
pub fn cas_u32(addr &u32, old u32, new u32) bool {
|
|
mut swapped := false
|
|
asm volatile i386 {
|
|
mov edx, addr
|
|
test edx, 3
|
|
jz '1f'
|
|
call panicUnaligned
|
|
jmp '2f'
|
|
1:
|
|
mov eax, old
|
|
mov ecx, new
|
|
lock cmpxchg [edx], ecx
|
|
sete al
|
|
mov swapped, al
|
|
2:
|
|
; =m (swapped)
|
|
; r (addr)
|
|
r (old)
|
|
r (new)
|
|
; eax
|
|
ecx
|
|
edx
|
|
memory
|
|
}
|
|
return swapped
|
|
}
|
|
|
|
// load_u64 atomically loads and returns the value at num using MMX instructions.
|
|
// The operation is performed with sequential consistency.
|
|
// Requires MMX support. Panics if num is not 8-byte aligned.
|
|
pub fn load_u64(num &u64) u64 {
|
|
mut out := u64(0)
|
|
asm volatile i386 {
|
|
mov esi, num
|
|
test esi, 7
|
|
jz '1f'
|
|
call panicUnaligned
|
|
jmp '2f'
|
|
1:
|
|
movq mm0, [esi]
|
|
movq out, mm0
|
|
emms
|
|
2:
|
|
; =m (out)
|
|
; r (num)
|
|
; esi
|
|
mm0
|
|
memory
|
|
}
|
|
return out
|
|
}
|
|
|
|
// store_u64 atomically stores value at dest using MMX instructions.
|
|
// The operation is performed with sequential consistency.
|
|
// Requires MMX support. Panics if dest is not 8-byte aligned.
|
|
pub fn store_u64(dest &u64, value u64) {
|
|
asm volatile i386 {
|
|
mov esi, dest
|
|
test esi, 7
|
|
jz '1f'
|
|
call panicUnaligned
|
|
jmp '2f'
|
|
1:
|
|
movq mm0, value
|
|
movq [esi], mm0
|
|
emms
|
|
xor eax, eax
|
|
lock xaddl [esp], eax
|
|
2:
|
|
; ; r (dest)
|
|
m (value)
|
|
; eax
|
|
mm0
|
|
memory
|
|
}
|
|
}
|
|
|
|
// add_u64 atomically adds delta to the value at dest and returns the new value.
|
|
// Uses a compare-and-swap loop. The operation is performed with sequential consistency.
|
|
// Panics if dest is not 8-byte aligned.
|
|
pub fn add_u64(dest &u64, delta u64) u64 {
|
|
mut delta_lo := u32(delta & 0xFFFF_FFFF)
|
|
mut delta_hi := u32(delta >> 32)
|
|
mut res_lo := u32(0)
|
|
mut res_hi := u32(0)
|
|
asm volatile i386 {
|
|
mov esi, dest
|
|
test esi, 7
|
|
jz '1f'
|
|
call panicUnaligned
|
|
jmp '2f'
|
|
1:
|
|
3:
|
|
mov eax, [esi]
|
|
mov edx, [esi + 4]
|
|
mov ebx, eax
|
|
mov ecx, edx
|
|
add ebx, delta_lo
|
|
adc ecx, delta_hi
|
|
lock cmpxchg8b [esi]
|
|
jnz '3b'
|
|
mov res_lo, ebx
|
|
mov res_hi, ecx
|
|
2:
|
|
; ; r (dest)
|
|
m (delta_lo)
|
|
m (delta_hi)
|
|
m (res_lo)
|
|
m (res_hi)
|
|
; eax
|
|
ebx
|
|
ecx
|
|
edx
|
|
esi
|
|
memory
|
|
}
|
|
return u64(res_lo) | (u64(res_hi) << 32)
|
|
}
|
|
|
|
// swap_u64 atomically stores value at dest and returns the old value.
|
|
// Uses a compare-and-swap loop. The operation is performed with sequential consistency.
|
|
// Panics if dest is not 8-byte aligned.
|
|
pub fn swap_u64(dest &u64, value u64) u64 {
|
|
mut old := u64(0)
|
|
mut value_lo := u32(value & 0xFFFF_FFFF)
|
|
mut value_hi := u32(value >> 32)
|
|
asm volatile i386 {
|
|
mov esi, dest
|
|
test esi, 7
|
|
jz '1f'
|
|
call panicUnaligned
|
|
jmp '2f'
|
|
1:
|
|
3:
|
|
mov eax, [esi]
|
|
mov edx, [esi + 4]
|
|
mov ebx, value_lo
|
|
mov ecx, value_hi
|
|
lock cmpxchg8b [esi]
|
|
jnz '3b'
|
|
mov value_lo, eax
|
|
mov value_hi, edx
|
|
2:
|
|
; ; r (dest)
|
|
m (value_lo)
|
|
m (value_hi)
|
|
; eax
|
|
ebx
|
|
ecx
|
|
edx
|
|
esi
|
|
memory
|
|
}
|
|
old = u64(value_lo) | (u64(value_hi) << 32)
|
|
return old
|
|
}
|
|
|
|
// cas_u64 performs a compare-and-swap operation.
|
|
// If the current value at addr equals old, it atomically stores new.
|
|
// Returns true if the swap was performed, false otherwise.
|
|
// The operation is performed with sequential consistency.
|
|
// Panics if addr is not 8-byte aligned.
|
|
pub fn cas_u64(addr &u64, old u64, new u64) bool {
|
|
mut swapped := false
|
|
mut old_lo := u32(old & 0xFFFF_FFFF)
|
|
mut old_hi := u32(old >> 32)
|
|
mut new_lo := u32(new & 0xFFFF_FFFF)
|
|
mut new_hi := u32(new >> 32)
|
|
asm volatile i386 {
|
|
mov esi, addr
|
|
test esi, 7
|
|
jz '1f'
|
|
call panicUnaligned
|
|
jmp '2f'
|
|
1:
|
|
mov eax, old_lo
|
|
mov edx, old_hi
|
|
mov ebx, new_lo
|
|
mov ecx, new_hi
|
|
lock cmpxchg8b [esi]
|
|
sete al
|
|
mov swapped, al
|
|
2:
|
|
; =m (swapped)
|
|
; r (addr)
|
|
m (old_lo)
|
|
m (old_hi)
|
|
m (new_lo)
|
|
m (new_hi)
|
|
; eax
|
|
ebx
|
|
ecx
|
|
edx
|
|
esi
|
|
memory
|
|
}
|
|
return swapped
|
|
}
|
|
|
|
// and_i64 atomically performs a bitwise AND of the value at addr with mask and returns the old value.
|
|
// The operation is performed with sequential consistency.
|
|
// Panics if addr is not 8-byte aligned.
|
|
pub fn and_i64(addr &i64, mask i64) i64 {
|
|
mask_lo := u32(u64(mask) & 0xFFFF_FFFF)
|
|
mask_hi := u32(u64(mask) >> 32)
|
|
mut old_lo := u32(0)
|
|
mut old_hi := u32(0)
|
|
|
|
asm volatile i386 {
|
|
mov esi, addr
|
|
test esi, 7
|
|
jz '1f'
|
|
call panicUnaligned
|
|
jmp '2f'
|
|
1:
|
|
mov eax, [esi]
|
|
mov edx, [esi + 4]
|
|
3:
|
|
mov ebx, eax
|
|
and ebx, mask_lo
|
|
mov ecx, edx
|
|
and ecx, mask_hi
|
|
lock cmpxchg8b [esi]
|
|
jnz '3b'
|
|
mov old_lo, eax
|
|
mov old_hi, edx
|
|
2:
|
|
; =m (old_lo)
|
|
=m (old_hi)
|
|
; m (mask_lo)
|
|
m (mask_hi)
|
|
r (addr)
|
|
; eax
|
|
edx
|
|
ecx
|
|
ebx
|
|
esi
|
|
}
|
|
return i64(u64(old_lo) | (u64(old_hi) << 32))
|
|
}
|
|
|
|
// and_u64 atomically performs a bitwise AND of the value at addr with mask and returns the old value.
|
|
// The operation is performed with sequential consistency.
|
|
// Panics if addr is not 8-byte aligned.
|
|
pub fn and_u64(addr &u64, mask u64) u64 {
|
|
mask_lo := u32(u64(mask) & 0xFFFF_FFFF)
|
|
mask_hi := u32(u64(mask) >> 32)
|
|
mut old_lo := u32(0)
|
|
mut old_hi := u32(0)
|
|
|
|
asm volatile i386 {
|
|
mov esi, addr
|
|
test esi, 7
|
|
jz '1f'
|
|
call panicUnaligned
|
|
jmp '2f'
|
|
1:
|
|
mov eax, [esi]
|
|
mov edx, [esi + 4]
|
|
3:
|
|
mov ebx, eax
|
|
and ebx, mask_lo
|
|
mov ecx, edx
|
|
and ecx, mask_hi
|
|
lock cmpxchg8b [esi]
|
|
jnz '3b'
|
|
mov old_lo, eax
|
|
mov old_hi, edx
|
|
2:
|
|
; =m (old_lo)
|
|
=m (old_hi)
|
|
; m (mask_lo)
|
|
m (mask_hi)
|
|
r (addr)
|
|
; eax
|
|
edx
|
|
ecx
|
|
ebx
|
|
esi
|
|
}
|
|
return u64(old_lo) | (u64(old_hi) << 32)
|
|
}
|
|
|
|
// or_i64 atomically performs a bitwise OR of the value at addr with mask and returns the old value.
|
|
// The operation is performed with sequential consistency.
|
|
// Panics if addr is not 8-byte aligned.
|
|
pub fn or_i64(addr &i64, mask i64) i64 {
|
|
mask_lo := u32(u64(mask) & 0xFFFF_FFFF)
|
|
mask_hi := u32(u64(mask) >> 32)
|
|
mut old_lo := u32(0)
|
|
mut old_hi := u32(0)
|
|
|
|
asm volatile i386 {
|
|
mov esi, addr
|
|
test esi, 7
|
|
jz '1f'
|
|
call panicUnaligned
|
|
jmp '2f'
|
|
1:
|
|
mov eax, [esi]
|
|
mov edx, [esi + 4]
|
|
3:
|
|
mov ebx, eax
|
|
or ebx, mask_lo
|
|
mov ecx, edx
|
|
or ecx, mask_hi
|
|
lock cmpxchg8b [esi]
|
|
jnz '3b'
|
|
mov old_lo, eax
|
|
mov old_hi, edx
|
|
2:
|
|
; =m (old_lo)
|
|
=m (old_hi)
|
|
; m (mask_lo)
|
|
m (mask_hi)
|
|
r (addr)
|
|
; eax
|
|
edx
|
|
ecx
|
|
ebx
|
|
esi
|
|
}
|
|
return i64(u64(old_lo) | (u64(old_hi) << 32))
|
|
}
|
|
|
|
// or_u64 atomically performs a bitwise OR of the value at addr with mask and returns the old value.
|
|
// The operation is performed with sequential consistency.
|
|
// Panics if addr is not 8-byte aligned.
|
|
pub fn or_u64(addr &u64, mask u64) u64 {
|
|
mask_lo := u32(u64(mask) & 0xFFFF_FFFF)
|
|
mask_hi := u32(u64(mask) >> 32)
|
|
mut old_lo := u32(0)
|
|
mut old_hi := u32(0)
|
|
|
|
asm volatile i386 {
|
|
mov esi, addr
|
|
test esi, 7
|
|
jz '1f'
|
|
call panicUnaligned
|
|
jmp '2f'
|
|
1:
|
|
mov eax, [esi]
|
|
mov edx, [esi + 4]
|
|
3:
|
|
mov ebx, eax
|
|
or ebx, mask_lo
|
|
mov ecx, edx
|
|
or ecx, mask_hi
|
|
lock cmpxchg8b [esi]
|
|
jnz '3b'
|
|
mov old_lo, eax
|
|
mov old_hi, edx
|
|
2:
|
|
; =m (old_lo)
|
|
=m (old_hi)
|
|
; m (mask_lo)
|
|
m (mask_hi)
|
|
r (addr)
|
|
; eax
|
|
edx
|
|
ecx
|
|
ebx
|
|
esi
|
|
}
|
|
return u64(old_lo) | (u64(old_hi) << 32)
|
|
}
|
|
|
|
// and_u32 atomically performs a bitwise AND of the value at addr with mask and returns the old value.
|
|
// The operation is performed with sequential consistency.
|
|
// Panics if addr is not 4-byte aligned.
|
|
pub fn and_u32(addr &u32, mask u32) u32 {
|
|
mut old := u32(0)
|
|
|
|
asm volatile i386 {
|
|
mov edx, addr
|
|
test edx, 3
|
|
jz '1f'
|
|
call panicUnaligned
|
|
jmp '2f'
|
|
1:
|
|
3:
|
|
mov eax, [edx]
|
|
mov ecx, eax
|
|
and ecx, mask
|
|
lock cmpxchgl [edx], ecx
|
|
jnz '3b'
|
|
mov old, eax
|
|
2:
|
|
; =r (old)
|
|
; r (addr)
|
|
r (mask)
|
|
; edx
|
|
eax
|
|
ecx
|
|
memory
|
|
}
|
|
return old
|
|
}
|
|
|
|
// and_i32 atomically performs a bitwise AND of the value at addr with mask and returns the old value.
|
|
// The operation is performed with sequential consistency.
|
|
// Panics if addr is not 4-byte aligned.
|
|
pub fn and_i32(addr &i32, mask i32) i32 {
|
|
mut old := i32(0)
|
|
|
|
asm volatile i386 {
|
|
mov edx, addr
|
|
test edx, 3
|
|
jz '1f'
|
|
call panicUnaligned
|
|
jmp '2f'
|
|
1:
|
|
3:
|
|
mov eax, [edx]
|
|
mov ecx, eax
|
|
and ecx, mask
|
|
lock cmpxchgl [edx], ecx
|
|
jnz '3b'
|
|
mov old, eax
|
|
2:
|
|
; =r (old)
|
|
; r (addr)
|
|
r (mask)
|
|
; edx
|
|
eax
|
|
ecx
|
|
memory
|
|
}
|
|
return old
|
|
}
|
|
|
|
// or_i32 atomically performs a bitwise OR of the value at addr with mask and returns the old value.
|
|
// The operation is performed with sequential consistency.
|
|
// Panics if addr is not 4-byte aligned.
|
|
pub fn or_i32(addr &i32, mask i32) i32 {
|
|
mut old := i32(0)
|
|
|
|
asm volatile i386 {
|
|
mov edx, addr
|
|
test edx, 3
|
|
jz '1f'
|
|
call panicUnaligned
|
|
jmp '2f'
|
|
1:
|
|
3:
|
|
mov eax, [edx]
|
|
mov ecx, eax
|
|
or ecx, mask
|
|
lock cmpxchgl [edx], ecx
|
|
jnz '3b'
|
|
mov old, eax
|
|
2:
|
|
; =r (old)
|
|
; r (addr)
|
|
r (mask)
|
|
; edx
|
|
eax
|
|
ecx
|
|
memory
|
|
}
|
|
return old
|
|
}
|
|
|
|
// or_u32 atomically performs a bitwise OR of the value at addr with mask and returns the old value.
|
|
// The operation is performed with sequential consistency.
|
|
// Panics if addr is not 4-byte aligned.
|
|
pub fn or_u32(addr &u32, mask u32) u32 {
|
|
mut old := u32(0)
|
|
|
|
asm volatile i386 {
|
|
mov edx, addr
|
|
test edx, 3
|
|
jz '1f'
|
|
call panicUnaligned
|
|
jmp '2f'
|
|
1:
|
|
3:
|
|
mov eax, [edx]
|
|
mov ecx, eax
|
|
or ecx, mask
|
|
lock cmpxchgl [edx], ecx
|
|
jnz '3b'
|
|
mov old, eax
|
|
2:
|
|
; =r (old)
|
|
; r (addr)
|
|
r (mask)
|
|
; edx
|
|
eax
|
|
ecx
|
|
memory
|
|
}
|
|
return old
|
|
}
|