|
| 1 | +//go:build amd64 && !purego |
| 2 | + |
| 3 | +package base58 |
| 4 | + |
| 5 | +// Kernels in avx2_amd64.s. Encoders return the length n and clobber dst[n:]. |
| 6 | +// Decoders take 32..44 / 64..88 chars and return 0 (ok), 1 (ErrInvalidChar) |
| 7 | +// or 2 (ErrValueTooLarge); leading-'1' validation is left to the caller. |
| 8 | + |
| 9 | +//go:noescape |
| 10 | +func encode32AVX2(src *[32]byte, dst *[48]byte) int |
| 11 | + |
| 12 | +//go:noescape |
| 13 | +func encode64AVX2(src *[64]byte, dst *[96]byte) int |
| 14 | + |
| 15 | +//go:noescape |
| 16 | +func decode32AVX2(s *byte, n int, dst *[32]byte) int |
| 17 | + |
| 18 | +//go:noescape |
| 19 | +func decode64AVX2(s *byte, n int, dst *[64]byte) int |
| 20 | + |
| 21 | +// Tables widened to qwords (rows padded to 4-lane multiples) for VPMULUDQ. |
| 22 | +var ( |
| 23 | + encTable32q [binarySz32][8]uint64 |
| 24 | + encTable64q [binarySz64][20]uint64 |
| 25 | + decTable32q [intermediateSz32][8]uint64 |
| 26 | + decTable64q [intermediateSz64][16]uint64 |
| 27 | +) |
| 28 | + |
| 29 | +func init() { |
| 30 | + for i, row := range encTable32 { |
| 31 | + for k, v := range row { |
| 32 | + encTable32q[i][k] = uint64(v) |
| 33 | + } |
| 34 | + } |
| 35 | + for i, row := range encTable64 { |
| 36 | + for k, v := range row { |
| 37 | + encTable64q[i][k] = uint64(v) |
| 38 | + } |
| 39 | + } |
| 40 | + for i, row := range decTable32 { |
| 41 | + for k, v := range row { |
| 42 | + decTable32q[i][k] = uint64(v) |
| 43 | + } |
| 44 | + } |
| 45 | + for i, row := range decTable64 { |
| 46 | + for k, v := range row { |
| 47 | + decTable64q[i][k] = uint64(v) |
| 48 | + } |
| 49 | + } |
| 50 | +} |
| 51 | + |
| 52 | +// rep tiles b into a 32-byte vector constant. |
| 53 | +// |
| 54 | +//nolint:unused // referenced from avx2_amd64.s |
| 55 | +func rep(b ...byte) (out [32]byte) { |
| 56 | + for i := range out { |
| 57 | + out[i] = b[i%len(b)] |
| 58 | + } |
| 59 | + return |
| 60 | +} |
| 61 | + |
| 62 | +//nolint:unused // referenced from avx2_amd64.s |
| 63 | +var ( |
| 64 | + avxBswap = rep(3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12) |
| 65 | + avxIota = rep(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15) |
| 66 | + avxSpread = rep(0, 1, 1, 1, 1, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) |
| 67 | + avxP = rep(0, 1, 2, 3, 5, 6, 7, 8, 10, 11, 12, 13, 0x80, 0x80, 0x80, 0x80) |
| 68 | + avxQ = rep(4, 0x80, 0x80, 0x80, 9, 0x80, 0x80, 0x80, 14, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80) |
| 69 | + avxTail = [32]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, |
| 70 | + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0x80} |
| 71 | + avxW1 = rep(58, 1) |
| 72 | + avxW2 = rep(0x24, 0x0D, 1, 0) // int16 {3364, 1} |
| 73 | + // valid base58 char iff lo[c&15]&hi[c>>4] != 0 |
| 74 | + avxLoNib = rep(20, 31, 31, 31, 31, 31, 31, 31, 31, 29, 30, 10, 2, 10, 10, 8) |
| 75 | + avxHiNib = rep(0, 0, 0, 1, 2, 4, 8, 16, 0, 0, 0, 0, 0, 0, 0, 0) |
| 76 | + avxB8 = rep(8) |
| 77 | + avxB16 = rep(16) |
| 78 | + avxB21 = rep(21) |
| 79 | + avxB32 = rep(32) |
| 80 | + avxB43 = rep(43) |
| 81 | + avxB64 = rep(64) |
| 82 | + avxB73 = rep(73) |
| 83 | + avxB79 = rep(79) |
| 84 | + avxB96 = rep(96) |
| 85 | + avxB108 = rep(108) |
| 86 | + avxBm6 = rep(0xFA) // -6 |
| 87 | + avxBm7 = rep(0xF9) // -7 |
| 88 | + avxBm49 = rep(0xCF) // -'1' |
| 89 | + avxB15 = rep(0x0F) |
| 90 | + avxD58 = rep(58, 0, 0, 0) |
| 91 | + avxDivA = rep(0x09, 0xCB, 0x3D, 0x8D, 0, 0, 0, 0) // 2369637129 = 2^37/58 |
| 92 | + avxDivB = rep(0x93, 0x20, 0xED, 0x4D, 0, 0, 0, 0) // 1307386003 = 2^42/58^2 |
| 93 | +) |
0 commit comments