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  }