github.com/devfans/go-ethereum@v1.5.10-0.20170326212234-7419d0c38291/pow/xor.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 5 // Source: https://golang.org/src/crypto/cipher/xor.go 6 7 package pow 8 9 import ( 10 "runtime" 11 "unsafe" 12 ) 13 14 const wordSize = int(unsafe.Sizeof(uintptr(0))) 15 const supportsUnaligned = runtime.GOARCH == "386" || runtime.GOARCH == "amd64" || runtime.GOARCH == "ppc64" || runtime.GOARCH == "ppc64le" || runtime.GOARCH == "s390x" 16 17 // fastXORBytes xors in bulk. It only works on architectures that 18 // support unaligned read/writes. 19 func fastXORBytes(dst, a, b []byte) int { 20 n := len(a) 21 if len(b) < n { 22 n = len(b) 23 } 24 25 w := n / wordSize 26 if w > 0 { 27 dw := *(*[]uintptr)(unsafe.Pointer(&dst)) 28 aw := *(*[]uintptr)(unsafe.Pointer(&a)) 29 bw := *(*[]uintptr)(unsafe.Pointer(&b)) 30 for i := 0; i < w; i++ { 31 dw[i] = aw[i] ^ bw[i] 32 } 33 } 34 35 for i := (n - n%wordSize); i < n; i++ { 36 dst[i] = a[i] ^ b[i] 37 } 38 39 return n 40 } 41 42 func safeXORBytes(dst, a, b []byte) int { 43 n := len(a) 44 if len(b) < n { 45 n = len(b) 46 } 47 for i := 0; i < n; i++ { 48 dst[i] = a[i] ^ b[i] 49 } 50 return n 51 } 52 53 // xorBytes xors the bytes in a and b. The destination is assumed to have enough 54 // space. Returns the number of bytes xor'd. 55 func xorBytes(dst, a, b []byte) int { 56 if supportsUnaligned { 57 return fastXORBytes(dst, a, b) 58 } 59 // TODO(hanwen): if (dst, a, b) have common alignment 60 // we could still try fastXORBytes. It is not clear 61 // how often this happens, and it's only worth it if 62 // the block encryption itself is hardware 63 // accelerated. 64 return safeXORBytes(dst, a, b) 65 } 66 67 // fastXORWords XORs multiples of 4 or 8 bytes (depending on architecture.) 68 // The arguments are assumed to be of equal length. 69 func fastXORWords(dst, a, b []byte) { 70 dw := *(*[]uintptr)(unsafe.Pointer(&dst)) 71 aw := *(*[]uintptr)(unsafe.Pointer(&a)) 72 bw := *(*[]uintptr)(unsafe.Pointer(&b)) 73 n := len(b) / wordSize 74 for i := 0; i < n; i++ { 75 dw[i] = aw[i] ^ bw[i] 76 } 77 } 78 79 func xorWords(dst, a, b []byte) { 80 if supportsUnaligned { 81 fastXORWords(dst, a, b) 82 } else { 83 safeXORBytes(dst, a, b) 84 } 85 }