blob: 197fe634e0e9d9e9555bcfb9fbfdac07e716046f [file] [edit]
// Copyright 2025 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build (mips || mipsle || mips64 || mips64le) && !purego
package subtle
import (
"unsafe"
)
const wordSize = unsafe.Sizeof(uintptr(0))
// dst,a,b,n, all be wordSize aligned, and n must be > 0 and a multiple of wordSize
//
//go:noescape
func xorBytesAligned(dst, a, b *byte, n int)
func xorBytes(dstb, xb, yb *byte, n int) {
xp := uintptr(unsafe.Pointer(xb)) % wordSize
yp := uintptr(unsafe.Pointer(yb)) % wordSize
dp := uintptr(unsafe.Pointer(dstb)) % wordSize
if xp != yp || xp != dp {
dst := unsafe.Slice(dstb, n)
x := unsafe.Slice(xb, n)
y := unsafe.Slice(yb, n)
xorLoop(dst, x, y)
return
}
for (uintptr(unsafe.Pointer(dstb))%wordSize) != 0 && n > 0 {
*dstb = *xb ^ *yb
dstb = (*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(dstb)) + 1))
xb = (*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(xb)) + 1))
yb = (*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(yb)) + 1))
n--
}
alignedN := n & -int(wordSize)
if alignedN > 0 {
xorBytesAligned(dstb, xb, yb, alignedN)
dstb = (*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(dstb)) + uintptr(alignedN)))
xb = (*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(xb)) + uintptr(alignedN)))
yb = (*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(yb)) + uintptr(alignedN)))
n -= alignedN
}
for n > 0 {
*dstb = *xb ^ *yb
dstb = (*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(dstb)) + 1))
xb = (*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(xb)) + 1))
yb = (*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(yb)) + 1))
n--
}
}
func xorLoop[T byte | uintptr](dst, x, y []T) {
x = x[:len(dst)] // remove bounds check in loop
y = y[:len(dst)] // remove bounds check in loop
for i := range dst {
dst[i] = x[i] ^ y[i]
}
}