xor.go 2.5 KB

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