// 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] } }