github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/internal/xor/xor_generic.go (about) 1 // Copyright 2013 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 //go:build !amd64 && !arm64 5 // +build !amd64,!arm64 6 7 package xor 8 9 import ( 10 "runtime" 11 "unsafe" 12 ) 13 14 // xorBytes xors the bytes in a and b. The destination should have enough 15 // space, otherwise xorBytes will panic. Returns the number of bytes xor'd. 16 func XorBytes(dst, a, b []byte) int { 17 n := len(a) 18 if len(b) < n { 19 n = len(b) 20 } 21 if n == 0 { 22 return 0 23 } 24 25 switch { 26 case supportsUnaligned: 27 fastXORBytes(dst, a, b, n) 28 default: 29 // TODO(hanwen): if (dst, a, b) have common alignment 30 // we could still try fastXORBytes. It is not clear 31 // how often this happens, and it's only worth it if 32 // the block encryption itself is hardware 33 // accelerated. 34 safeXORBytes(dst, a, b, n) 35 } 36 return n 37 } 38 39 const wordSize = int(unsafe.Sizeof(uintptr(0))) 40 const supportsUnaligned = runtime.GOARCH == "386" || runtime.GOARCH == "ppc64" || runtime.GOARCH == "ppc64le" || runtime.GOARCH == "s390x" 41 42 // fastXORBytes xors in bulk. It only works on architectures that 43 // support unaligned read/writes. 44 // n needs to be smaller or equal than the length of a and b. 45 func fastXORBytes(dst, a, b []byte, n int) { 46 // Assert dst has enough space 47 _ = dst[n-1] 48 49 w := n / wordSize 50 if w > 0 { 51 dw := *(*[]uintptr)(unsafe.Pointer(&dst)) 52 aw := *(*[]uintptr)(unsafe.Pointer(&a)) 53 bw := *(*[]uintptr)(unsafe.Pointer(&b)) 54 for i := 0; i < w; i++ { 55 dw[i] = aw[i] ^ bw[i] 56 } 57 } 58 59 for i := (n - n%wordSize); i < n; i++ { 60 dst[i] = a[i] ^ b[i] 61 } 62 } 63 64 // n needs to be smaller or equal than the length of a and b. 65 func safeXORBytes(dst, a, b []byte, n int) { 66 for i := 0; i < n; i++ { 67 dst[i] = a[i] ^ b[i] 68 } 69 } 70 71 // fastXORWords XORs multiples of 4 or 8 bytes (depending on architecture.) 72 // The arguments are assumed to be of equal length. 73 func fastXORWords(dst, a, b []byte) { 74 dw := *(*[]uintptr)(unsafe.Pointer(&dst)) 75 aw := *(*[]uintptr)(unsafe.Pointer(&a)) 76 bw := *(*[]uintptr)(unsafe.Pointer(&b)) 77 n := len(b) / wordSize 78 for i := 0; i < n; i++ { 79 dw[i] = aw[i] ^ bw[i] 80 } 81 } 82 83 // fastXORWords XORs multiples of 4 or 8 bytes (depending on architecture.) 84 // The slice arguments a and b are assumed to be of equal length. 85 func XorWords(dst, a, b []byte) { 86 if supportsUnaligned { 87 fastXORWords(dst, a, b) 88 } else { 89 safeXORBytes(dst, a, b, len(b)) 90 } 91 }