fix(go.sum): update ResolveSpec dependency to v1.0.87
CI / build-and-test (push) Failing after 1s
Release / release (push) Failing after 19m26s

This commit is contained in:
Hein
2026-06-23 13:17:16 +02:00
parent 0227912325
commit 1adf50e3db
2436 changed files with 1078758 additions and 114 deletions
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021 Segment
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+53
View File
@@ -0,0 +1,53 @@
package ascii
import _ "github.com/segmentio/asm/cpu"
// https://graphics.stanford.edu/~seander/bithacks.html#HasLessInWord
const (
hasLessConstL64 = (^uint64(0)) / 255
hasLessConstR64 = hasLessConstL64 * 128
hasLessConstL32 = (^uint32(0)) / 255
hasLessConstR32 = hasLessConstL32 * 128
hasMoreConstL64 = (^uint64(0)) / 255
hasMoreConstR64 = hasMoreConstL64 * 128
hasMoreConstL32 = (^uint32(0)) / 255
hasMoreConstR32 = hasMoreConstL32 * 128
)
func hasLess64(x, n uint64) bool {
return ((x - (hasLessConstL64 * n)) & ^x & hasLessConstR64) != 0
}
func hasLess32(x, n uint32) bool {
return ((x - (hasLessConstL32 * n)) & ^x & hasLessConstR32) != 0
}
func hasMore64(x, n uint64) bool {
return (((x + (hasMoreConstL64 * (127 - n))) | x) & hasMoreConstR64) != 0
}
func hasMore32(x, n uint32) bool {
return (((x + (hasMoreConstL32 * (127 - n))) | x) & hasMoreConstR32) != 0
}
var lowerCase = [256]byte{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
}
+30
View File
@@ -0,0 +1,30 @@
package ascii
import (
"github.com/segmentio/asm/internal/unsafebytes"
)
// EqualFold is a version of bytes.EqualFold designed to work on ASCII input
// instead of UTF-8.
//
// When the program has guarantees that the input is composed of ASCII
// characters only, it allows for greater optimizations.
func EqualFold(a, b []byte) bool {
return EqualFoldString(unsafebytes.String(a), unsafebytes.String(b))
}
func HasPrefixFold(s, prefix []byte) bool {
return len(s) >= len(prefix) && EqualFold(s[:len(prefix)], prefix)
}
func HasSuffixFold(s, suffix []byte) bool {
return len(s) >= len(suffix) && EqualFold(s[len(s)-len(suffix):], suffix)
}
func HasPrefixFoldString(s, prefix string) bool {
return len(s) >= len(prefix) && EqualFoldString(s[:len(prefix)], prefix)
}
func HasSuffixFoldString(s, suffix string) bool {
return len(s) >= len(suffix) && EqualFoldString(s[len(s)-len(suffix):], suffix)
}
+13
View File
@@ -0,0 +1,13 @@
// Code generated by command: go run equal_fold_asm.go -pkg ascii -out ../ascii/equal_fold_amd64.s -stubs ../ascii/equal_fold_amd64.go. DO NOT EDIT.
//go:build !purego
// +build !purego
package ascii
// EqualFoldString is a version of strings.EqualFold designed to work on ASCII
// input instead of UTF-8.
//
// When the program has guarantees that the input is composed of ASCII
// characters only, it allows for greater optimizations.
func EqualFoldString(a string, b string) bool
+304
View File
@@ -0,0 +1,304 @@
// Code generated by command: go run equal_fold_asm.go -pkg ascii -out ../ascii/equal_fold_amd64.s -stubs ../ascii/equal_fold_amd64.go. DO NOT EDIT.
//go:build !purego
// +build !purego
#include "textflag.h"
// func EqualFoldString(a string, b string) bool
// Requires: AVX, AVX2, SSE4.1
TEXT ·EqualFoldString(SB), NOSPLIT, $0-33
MOVQ a_base+0(FP), CX
MOVQ a_len+8(FP), DX
MOVQ b_base+16(FP), BX
CMPQ DX, b_len+24(FP)
JNE done
XORQ AX, AX
CMPQ DX, $0x10
JB init_x86
BTL $0x08, github·comsegmentioasmcpu·X86+0(SB)
JCS init_avx
init_x86:
LEAQ github·comsegmentioasmascii·lowerCase+0(SB), R9
XORL SI, SI
cmp8:
CMPQ DX, $0x08
JB cmp7
MOVBLZX (CX)(AX*1), DI
MOVBLZX (BX)(AX*1), R8
MOVB (R9)(DI*1), DI
XORB (R9)(R8*1), DI
ORB DI, SI
MOVBLZX 1(CX)(AX*1), DI
MOVBLZX 1(BX)(AX*1), R8
MOVB (R9)(DI*1), DI
XORB (R9)(R8*1), DI
ORB DI, SI
MOVBLZX 2(CX)(AX*1), DI
MOVBLZX 2(BX)(AX*1), R8
MOVB (R9)(DI*1), DI
XORB (R9)(R8*1), DI
ORB DI, SI
MOVBLZX 3(CX)(AX*1), DI
MOVBLZX 3(BX)(AX*1), R8
MOVB (R9)(DI*1), DI
XORB (R9)(R8*1), DI
ORB DI, SI
MOVBLZX 4(CX)(AX*1), DI
MOVBLZX 4(BX)(AX*1), R8
MOVB (R9)(DI*1), DI
XORB (R9)(R8*1), DI
ORB DI, SI
MOVBLZX 5(CX)(AX*1), DI
MOVBLZX 5(BX)(AX*1), R8
MOVB (R9)(DI*1), DI
XORB (R9)(R8*1), DI
ORB DI, SI
MOVBLZX 6(CX)(AX*1), DI
MOVBLZX 6(BX)(AX*1), R8
MOVB (R9)(DI*1), DI
XORB (R9)(R8*1), DI
ORB DI, SI
MOVBLZX 7(CX)(AX*1), DI
MOVBLZX 7(BX)(AX*1), R8
MOVB (R9)(DI*1), DI
XORB (R9)(R8*1), DI
ORB DI, SI
JNE done
ADDQ $0x08, AX
SUBQ $0x08, DX
JMP cmp8
cmp7:
CMPQ DX, $0x07
JB cmp6
MOVBLZX 6(CX)(AX*1), DI
MOVBLZX 6(BX)(AX*1), R8
MOVB (R9)(DI*1), DI
XORB (R9)(R8*1), DI
ORB DI, SI
cmp6:
CMPQ DX, $0x06
JB cmp5
MOVBLZX 5(CX)(AX*1), DI
MOVBLZX 5(BX)(AX*1), R8
MOVB (R9)(DI*1), DI
XORB (R9)(R8*1), DI
ORB DI, SI
cmp5:
CMPQ DX, $0x05
JB cmp4
MOVBLZX 4(CX)(AX*1), DI
MOVBLZX 4(BX)(AX*1), R8
MOVB (R9)(DI*1), DI
XORB (R9)(R8*1), DI
ORB DI, SI
cmp4:
CMPQ DX, $0x04
JB cmp3
MOVBLZX 3(CX)(AX*1), DI
MOVBLZX 3(BX)(AX*1), R8
MOVB (R9)(DI*1), DI
XORB (R9)(R8*1), DI
ORB DI, SI
cmp3:
CMPQ DX, $0x03
JB cmp2
MOVBLZX 2(CX)(AX*1), DI
MOVBLZX 2(BX)(AX*1), R8
MOVB (R9)(DI*1), DI
XORB (R9)(R8*1), DI
ORB DI, SI
cmp2:
CMPQ DX, $0x02
JB cmp1
MOVBLZX 1(CX)(AX*1), DI
MOVBLZX 1(BX)(AX*1), R8
MOVB (R9)(DI*1), DI
XORB (R9)(R8*1), DI
ORB DI, SI
cmp1:
CMPQ DX, $0x01
JB success
MOVBLZX (CX)(AX*1), DI
MOVBLZX (BX)(AX*1), R8
MOVB (R9)(DI*1), DI
XORB (R9)(R8*1), DI
ORB DI, SI
done:
SETEQ ret+32(FP)
RET
success:
MOVB $0x01, ret+32(FP)
RET
init_avx:
MOVB $0x20, SI
PINSRB $0x00, SI, X12
VPBROADCASTB X12, Y12
MOVB $0x1f, SI
PINSRB $0x00, SI, X13
VPBROADCASTB X13, Y13
MOVB $0x9a, SI
PINSRB $0x00, SI, X14
VPBROADCASTB X14, Y14
MOVB $0x01, SI
PINSRB $0x00, SI, X15
VPBROADCASTB X15, Y15
cmp128:
CMPQ DX, $0x80
JB cmp64
VMOVDQU (CX)(AX*1), Y0
VMOVDQU 32(CX)(AX*1), Y1
VMOVDQU 64(CX)(AX*1), Y2
VMOVDQU 96(CX)(AX*1), Y3
VMOVDQU (BX)(AX*1), Y4
VMOVDQU 32(BX)(AX*1), Y5
VMOVDQU 64(BX)(AX*1), Y6
VMOVDQU 96(BX)(AX*1), Y7
VXORPD Y0, Y4, Y4
VPCMPEQB Y12, Y4, Y8
VORPD Y12, Y0, Y0
VPADDB Y13, Y0, Y0
VPCMPGTB Y0, Y14, Y0
VPAND Y8, Y0, Y0
VPAND Y15, Y0, Y0
VPSLLW $0x05, Y0, Y0
VPCMPEQB Y4, Y0, Y0
VXORPD Y1, Y5, Y5
VPCMPEQB Y12, Y5, Y9
VORPD Y12, Y1, Y1
VPADDB Y13, Y1, Y1
VPCMPGTB Y1, Y14, Y1
VPAND Y9, Y1, Y1
VPAND Y15, Y1, Y1
VPSLLW $0x05, Y1, Y1
VPCMPEQB Y5, Y1, Y1
VXORPD Y2, Y6, Y6
VPCMPEQB Y12, Y6, Y10
VORPD Y12, Y2, Y2
VPADDB Y13, Y2, Y2
VPCMPGTB Y2, Y14, Y2
VPAND Y10, Y2, Y2
VPAND Y15, Y2, Y2
VPSLLW $0x05, Y2, Y2
VPCMPEQB Y6, Y2, Y2
VXORPD Y3, Y7, Y7
VPCMPEQB Y12, Y7, Y11
VORPD Y12, Y3, Y3
VPADDB Y13, Y3, Y3
VPCMPGTB Y3, Y14, Y3
VPAND Y11, Y3, Y3
VPAND Y15, Y3, Y3
VPSLLW $0x05, Y3, Y3
VPCMPEQB Y7, Y3, Y3
VPAND Y1, Y0, Y0
VPAND Y3, Y2, Y2
VPAND Y2, Y0, Y0
ADDQ $0x80, AX
SUBQ $0x80, DX
VPMOVMSKB Y0, SI
XORL $0xffffffff, SI
JNE done
JMP cmp128
cmp64:
CMPQ DX, $0x40
JB cmp32
VMOVDQU (CX)(AX*1), Y0
VMOVDQU 32(CX)(AX*1), Y1
VMOVDQU (BX)(AX*1), Y2
VMOVDQU 32(BX)(AX*1), Y3
VXORPD Y0, Y2, Y2
VPCMPEQB Y12, Y2, Y4
VORPD Y12, Y0, Y0
VPADDB Y13, Y0, Y0
VPCMPGTB Y0, Y14, Y0
VPAND Y4, Y0, Y0
VPAND Y15, Y0, Y0
VPSLLW $0x05, Y0, Y0
VPCMPEQB Y2, Y0, Y0
VXORPD Y1, Y3, Y3
VPCMPEQB Y12, Y3, Y5
VORPD Y12, Y1, Y1
VPADDB Y13, Y1, Y1
VPCMPGTB Y1, Y14, Y1
VPAND Y5, Y1, Y1
VPAND Y15, Y1, Y1
VPSLLW $0x05, Y1, Y1
VPCMPEQB Y3, Y1, Y1
VPAND Y1, Y0, Y0
ADDQ $0x40, AX
SUBQ $0x40, DX
VPMOVMSKB Y0, SI
XORL $0xffffffff, SI
JNE done
cmp32:
CMPQ DX, $0x20
JB cmp16
VMOVDQU (CX)(AX*1), Y0
VMOVDQU (BX)(AX*1), Y1
VXORPD Y0, Y1, Y1
VPCMPEQB Y12, Y1, Y2
VORPD Y12, Y0, Y0
VPADDB Y13, Y0, Y0
VPCMPGTB Y0, Y14, Y0
VPAND Y2, Y0, Y0
VPAND Y15, Y0, Y0
VPSLLW $0x05, Y0, Y0
VPCMPEQB Y1, Y0, Y0
ADDQ $0x20, AX
SUBQ $0x20, DX
VPMOVMSKB Y0, SI
XORL $0xffffffff, SI
JNE done
cmp16:
CMPQ DX, $0x10
JLE cmp_tail
VMOVDQU (CX)(AX*1), X0
VMOVDQU (BX)(AX*1), X1
VXORPD X0, X1, X1
VPCMPEQB X12, X1, X2
VORPD X12, X0, X0
VPADDB X13, X0, X0
VPCMPGTB X0, X14, X0
VPAND X2, X0, X0
VPAND X15, X0, X0
VPSLLW $0x05, X0, X0
VPCMPEQB X1, X0, X0
ADDQ $0x10, AX
SUBQ $0x10, DX
VPMOVMSKB X0, SI
XORL $0x0000ffff, SI
JNE done
cmp_tail:
SUBQ $0x10, DX
ADDQ DX, AX
VMOVDQU (CX)(AX*1), X0
VMOVDQU (BX)(AX*1), X1
VXORPD X0, X1, X1
VPCMPEQB X12, X1, X2
VORPD X12, X0, X0
VPADDB X13, X0, X0
VPCMPGTB X0, X14, X0
VPAND X2, X0, X0
VPAND X15, X0, X0
VPSLLW $0x05, X0, X0
VPCMPEQB X1, X0, X0
VPMOVMSKB X0, AX
XORL $0x0000ffff, AX
JMP done
+60
View File
@@ -0,0 +1,60 @@
//go:build purego || !amd64
// +build purego !amd64
package ascii
// EqualFoldString is a version of strings.EqualFold designed to work on ASCII
// input instead of UTF-8.
//
// When the program has guarantees that the input is composed of ASCII
// characters only, it allows for greater optimizations.
func EqualFoldString(a, b string) bool {
if len(a) != len(b) {
return false
}
var cmp byte
for len(a) >= 8 {
cmp |= lowerCase[a[0]] ^ lowerCase[b[0]]
cmp |= lowerCase[a[1]] ^ lowerCase[b[1]]
cmp |= lowerCase[a[2]] ^ lowerCase[b[2]]
cmp |= lowerCase[a[3]] ^ lowerCase[b[3]]
cmp |= lowerCase[a[4]] ^ lowerCase[b[4]]
cmp |= lowerCase[a[5]] ^ lowerCase[b[5]]
cmp |= lowerCase[a[6]] ^ lowerCase[b[6]]
cmp |= lowerCase[a[7]] ^ lowerCase[b[7]]
if cmp != 0 {
return false
}
a = a[8:]
b = b[8:]
}
switch len(a) {
case 7:
cmp |= lowerCase[a[6]] ^ lowerCase[b[6]]
fallthrough
case 6:
cmp |= lowerCase[a[5]] ^ lowerCase[b[5]]
fallthrough
case 5:
cmp |= lowerCase[a[4]] ^ lowerCase[b[4]]
fallthrough
case 4:
cmp |= lowerCase[a[3]] ^ lowerCase[b[3]]
fallthrough
case 3:
cmp |= lowerCase[a[2]] ^ lowerCase[b[2]]
fallthrough
case 2:
cmp |= lowerCase[a[1]] ^ lowerCase[b[1]]
fallthrough
case 1:
cmp |= lowerCase[a[0]] ^ lowerCase[b[0]]
}
return cmp == 0
}
+18
View File
@@ -0,0 +1,18 @@
package ascii
import "github.com/segmentio/asm/internal/unsafebytes"
// Valid returns true if b contains only ASCII characters.
func Valid(b []byte) bool {
return ValidString(unsafebytes.String(b))
}
// ValidBytes returns true if b is an ASCII character.
func ValidByte(b byte) bool {
return b <= 0x7f
}
// ValidBytes returns true if b is an ASCII character.
func ValidRune(r rune) bool {
return r <= 0x7f
}
+9
View File
@@ -0,0 +1,9 @@
// Code generated by command: go run valid_asm.go -pkg ascii -out ../ascii/valid_amd64.s -stubs ../ascii/valid_amd64.go. DO NOT EDIT.
//go:build !purego
// +build !purego
package ascii
// ValidString returns true if s contains only ASCII characters.
func ValidString(s string) bool
+132
View File
@@ -0,0 +1,132 @@
// Code generated by command: go run valid_asm.go -pkg ascii -out ../ascii/valid_amd64.s -stubs ../ascii/valid_amd64.go. DO NOT EDIT.
//go:build !purego
// +build !purego
#include "textflag.h"
// func ValidString(s string) bool
// Requires: AVX, AVX2, SSE4.1
TEXT ·ValidString(SB), NOSPLIT, $0-17
MOVQ s_base+0(FP), AX
MOVQ s_len+8(FP), CX
MOVQ $0x8080808080808080, DX
CMPQ CX, $0x10
JB cmp8
BTL $0x08, github·comsegmentioasmcpu·X86+0(SB)
JCS init_avx
cmp8:
CMPQ CX, $0x08
JB cmp4
TESTQ DX, (AX)
JNZ invalid
ADDQ $0x08, AX
SUBQ $0x08, CX
JMP cmp8
cmp4:
CMPQ CX, $0x04
JB cmp3
TESTL $0x80808080, (AX)
JNZ invalid
ADDQ $0x04, AX
SUBQ $0x04, CX
cmp3:
CMPQ CX, $0x03
JB cmp2
MOVWLZX (AX), CX
MOVBLZX 2(AX), AX
SHLL $0x10, AX
ORL CX, AX
TESTL $0x80808080, AX
JMP done
cmp2:
CMPQ CX, $0x02
JB cmp1
TESTW $0x8080, (AX)
JMP done
cmp1:
CMPQ CX, $0x00
JE done
TESTB $0x80, (AX)
done:
SETEQ ret+16(FP)
RET
invalid:
MOVB $0x00, ret+16(FP)
RET
init_avx:
PINSRQ $0x00, DX, X4
VPBROADCASTQ X4, Y4
cmp256:
CMPQ CX, $0x00000100
JB cmp128
VMOVDQU (AX), Y0
VPOR 32(AX), Y0, Y0
VMOVDQU 64(AX), Y1
VPOR 96(AX), Y1, Y1
VMOVDQU 128(AX), Y2
VPOR 160(AX), Y2, Y2
VMOVDQU 192(AX), Y3
VPOR 224(AX), Y3, Y3
VPOR Y1, Y0, Y0
VPOR Y3, Y2, Y2
VPOR Y2, Y0, Y0
VPTEST Y0, Y4
JNZ invalid
ADDQ $0x00000100, AX
SUBQ $0x00000100, CX
JMP cmp256
cmp128:
CMPQ CX, $0x80
JB cmp64
VMOVDQU (AX), Y0
VPOR 32(AX), Y0, Y0
VMOVDQU 64(AX), Y1
VPOR 96(AX), Y1, Y1
VPOR Y1, Y0, Y0
VPTEST Y0, Y4
JNZ invalid
ADDQ $0x80, AX
SUBQ $0x80, CX
cmp64:
CMPQ CX, $0x40
JB cmp32
VMOVDQU (AX), Y0
VPOR 32(AX), Y0, Y0
VPTEST Y0, Y4
JNZ invalid
ADDQ $0x40, AX
SUBQ $0x40, CX
cmp32:
CMPQ CX, $0x20
JB cmp16
VPTEST (AX), Y4
JNZ invalid
ADDQ $0x20, AX
SUBQ $0x20, CX
cmp16:
CMPQ CX, $0x10
JLE cmp_tail
VPTEST (AX), X4
JNZ invalid
ADDQ $0x10, AX
SUBQ $0x10, CX
cmp_tail:
SUBQ $0x10, CX
ADDQ CX, AX
VPTEST (AX), X4
JMP done
+48
View File
@@ -0,0 +1,48 @@
//go:build purego || !amd64
// +build purego !amd64
package ascii
import (
"unsafe"
)
// ValidString returns true if s contains only ASCII characters.
func ValidString(s string) bool {
p := *(*unsafe.Pointer)(unsafe.Pointer(&s))
i := uintptr(0)
n := uintptr(len(s))
for i+8 <= n {
if (*(*uint64)(unsafe.Pointer(uintptr(p) + i)) & 0x8080808080808080) != 0 {
return false
}
i += 8
}
if i+4 <= n {
if (*(*uint32)(unsafe.Pointer(uintptr(p) + i)) & 0x80808080) != 0 {
return false
}
i += 4
}
if i == n {
return true
}
p = unsafe.Pointer(uintptr(p) + i)
var x uint32
switch n - i {
case 3:
x = uint32(*(*uint16)(p)) | uint32(*(*uint8)(unsafe.Pointer(uintptr(p) + 2)))<<16
case 2:
x = uint32(*(*uint16)(p))
case 1:
x = uint32(*(*uint8)(p))
default:
return true
}
return (x & 0x80808080) == 0
}
+18
View File
@@ -0,0 +1,18 @@
package ascii
import "github.com/segmentio/asm/internal/unsafebytes"
// ValidPrint returns true if b contains only printable ASCII characters.
func ValidPrint(b []byte) bool {
return ValidPrintString(unsafebytes.String(b))
}
// ValidPrintBytes returns true if b is an ASCII character.
func ValidPrintByte(b byte) bool {
return 0x20 <= b && b <= 0x7e
}
// ValidPrintBytes returns true if b is an ASCII character.
func ValidPrintRune(r rune) bool {
return 0x20 <= r && r <= 0x7e
}
+9
View File
@@ -0,0 +1,9 @@
// Code generated by command: go run valid_print_asm.go -pkg ascii -out ../ascii/valid_print_amd64.s -stubs ../ascii/valid_print_amd64.go. DO NOT EDIT.
//go:build !purego
// +build !purego
package ascii
// ValidPrintString returns true if s contains only printable ASCII characters.
func ValidPrintString(s string) bool
+185
View File
@@ -0,0 +1,185 @@
// Code generated by command: go run valid_print_asm.go -pkg ascii -out ../ascii/valid_print_amd64.s -stubs ../ascii/valid_print_amd64.go. DO NOT EDIT.
//go:build !purego
// +build !purego
#include "textflag.h"
// func ValidPrintString(s string) bool
// Requires: AVX, AVX2, SSE4.1
TEXT ·ValidPrintString(SB), NOSPLIT, $0-17
MOVQ s_base+0(FP), AX
MOVQ s_len+8(FP), CX
CMPQ CX, $0x10
JB init_x86
BTL $0x08, github·comsegmentioasmcpu·X86+0(SB)
JCS init_avx
init_x86:
CMPQ CX, $0x08
JB cmp4
MOVQ $0xdfdfdfdfdfdfdfe0, DX
MOVQ $0x0101010101010101, BX
MOVQ $0x8080808080808080, SI
cmp8:
MOVQ (AX), DI
MOVQ DI, R8
LEAQ (DI)(DX*1), R9
NOTQ R8
ANDQ R8, R9
LEAQ (DI)(BX*1), R8
ORQ R8, DI
ORQ R9, DI
ADDQ $0x08, AX
SUBQ $0x08, CX
TESTQ SI, DI
JNE done
CMPQ CX, $0x08
JB cmp4
JMP cmp8
cmp4:
CMPQ CX, $0x04
JB cmp3
MOVL (AX), DX
MOVL DX, BX
LEAL 3755991008(DX), SI
NOTL BX
ANDL BX, SI
LEAL 16843009(DX), BX
ORL BX, DX
ORL SI, DX
ADDQ $0x04, AX
SUBQ $0x04, CX
TESTL $0x80808080, DX
JNE done
cmp3:
CMPQ CX, $0x03
JB cmp2
MOVWLZX (AX), DX
MOVBLZX 2(AX), AX
SHLL $0x10, AX
ORL DX, AX
ORL $0x20000000, AX
JMP final
cmp2:
CMPQ CX, $0x02
JB cmp1
MOVWLZX (AX), AX
ORL $0x20200000, AX
JMP final
cmp1:
CMPQ CX, $0x00
JE done
MOVBLZX (AX), AX
ORL $0x20202000, AX
final:
MOVL AX, CX
LEAL 3755991008(AX), DX
NOTL CX
ANDL CX, DX
LEAL 16843009(AX), CX
ORL CX, AX
ORL DX, AX
TESTL $0x80808080, AX
done:
SETEQ ret+16(FP)
RET
init_avx:
MOVB $0x1f, DL
PINSRB $0x00, DX, X8
VPBROADCASTB X8, Y8
MOVB $0x7e, DL
PINSRB $0x00, DX, X9
VPBROADCASTB X9, Y9
cmp128:
CMPQ CX, $0x80
JB cmp64
VMOVDQU (AX), Y0
VMOVDQU 32(AX), Y1
VMOVDQU 64(AX), Y2
VMOVDQU 96(AX), Y3
VPCMPGTB Y8, Y0, Y4
VPCMPGTB Y9, Y0, Y0
VPANDN Y4, Y0, Y0
VPCMPGTB Y8, Y1, Y5
VPCMPGTB Y9, Y1, Y1
VPANDN Y5, Y1, Y1
VPCMPGTB Y8, Y2, Y6
VPCMPGTB Y9, Y2, Y2
VPANDN Y6, Y2, Y2
VPCMPGTB Y8, Y3, Y7
VPCMPGTB Y9, Y3, Y3
VPANDN Y7, Y3, Y3
VPAND Y1, Y0, Y0
VPAND Y3, Y2, Y2
VPAND Y2, Y0, Y0
ADDQ $0x80, AX
SUBQ $0x80, CX
VPMOVMSKB Y0, DX
XORL $0xffffffff, DX
JNE done
JMP cmp128
cmp64:
CMPQ CX, $0x40
JB cmp32
VMOVDQU (AX), Y0
VMOVDQU 32(AX), Y1
VPCMPGTB Y8, Y0, Y2
VPCMPGTB Y9, Y0, Y0
VPANDN Y2, Y0, Y0
VPCMPGTB Y8, Y1, Y3
VPCMPGTB Y9, Y1, Y1
VPANDN Y3, Y1, Y1
VPAND Y1, Y0, Y0
ADDQ $0x40, AX
SUBQ $0x40, CX
VPMOVMSKB Y0, DX
XORL $0xffffffff, DX
JNE done
cmp32:
CMPQ CX, $0x20
JB cmp16
VMOVDQU (AX), Y0
VPCMPGTB Y8, Y0, Y1
VPCMPGTB Y9, Y0, Y0
VPANDN Y1, Y0, Y0
ADDQ $0x20, AX
SUBQ $0x20, CX
VPMOVMSKB Y0, DX
XORL $0xffffffff, DX
JNE done
cmp16:
CMPQ CX, $0x10
JLE cmp_tail
VMOVDQU (AX), X0
VPCMPGTB X8, X0, X1
VPCMPGTB X9, X0, X0
VPANDN X1, X0, X0
ADDQ $0x10, AX
SUBQ $0x10, CX
VPMOVMSKB X0, DX
XORL $0x0000ffff, DX
JNE done
cmp_tail:
SUBQ $0x10, CX
ADDQ CX, AX
VMOVDQU (AX), X0
VPCMPGTB X8, X0, X1
VPCMPGTB X9, X0, X0
VPANDN X1, X0, X0
VPMOVMSKB X0, DX
XORL $0x0000ffff, DX
JMP done
+46
View File
@@ -0,0 +1,46 @@
//go:build purego || !amd64
// +build purego !amd64
package ascii
import "unsafe"
// ValidString returns true if s contains only printable ASCII characters.
func ValidPrintString(s string) bool {
p := *(*unsafe.Pointer)(unsafe.Pointer(&s))
i := uintptr(0)
n := uintptr(len(s))
for i+8 <= n {
if hasLess64(*(*uint64)(unsafe.Pointer(uintptr(p) + i)), 0x20) || hasMore64(*(*uint64)(unsafe.Pointer(uintptr(p) + i)), 0x7e) {
return false
}
i += 8
}
if i+4 <= n {
if hasLess32(*(*uint32)(unsafe.Pointer(uintptr(p) + i)), 0x20) || hasMore32(*(*uint32)(unsafe.Pointer(uintptr(p) + i)), 0x7e) {
return false
}
i += 4
}
if i == n {
return true
}
p = unsafe.Pointer(uintptr(p) + i)
var x uint32
switch n - i {
case 3:
x = 0x20000000 | uint32(*(*uint16)(p)) | uint32(*(*uint8)(unsafe.Pointer(uintptr(p) + 2)))<<16
case 2:
x = 0x20200000 | uint32(*(*uint16)(p))
case 1:
x = 0x20202000 | uint32(*(*uint8)(p))
default:
return true
}
return !(hasLess32(x, 0x20) || hasMore32(x, 0x7e))
}
+67
View File
@@ -0,0 +1,67 @@
package base64
import (
"encoding/base64"
)
const (
StdPadding rune = base64.StdPadding
NoPadding rune = base64.NoPadding
encodeStd = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
encodeURL = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
encodeIMAP = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,"
letterRange = int8('Z' - 'A' + 1)
)
// StdEncoding is the standard base64 encoding, as defined in RFC 4648.
var StdEncoding = NewEncoding(encodeStd)
// URLEncoding is the alternate base64 encoding defined in RFC 4648.
// It is typically used in URLs and file names.
var URLEncoding = NewEncoding(encodeURL)
// RawStdEncoding is the standard unpadded base64 encoding defined in RFC 4648 section 3.2.
// This is the same as StdEncoding but omits padding characters.
var RawStdEncoding = StdEncoding.WithPadding(NoPadding)
// RawURLEncoding is the unpadded alternate base64 encoding defined in RFC 4648.
// This is the same as URLEncoding but omits padding characters.
var RawURLEncoding = URLEncoding.WithPadding(NoPadding)
// NewEncoding returns a new padded Encoding defined by the given alphabet,
// which must be a 64-byte string that does not contain the padding character
// or CR / LF ('\r', '\n'). Unlike the standard library, the encoding alphabet
// cannot be abitrary, and it must follow one of the know standard encoding
// variants.
//
// Required alphabet values:
// * [0,26): characters 'A'..'Z'
// * [26,52): characters 'a'..'z'
// * [52,62): characters '0'..'9'
// Flexible alphabet value options:
// * RFC 4648, RFC 1421, RFC 2045, RFC 2152, RFC 4880: '+' and '/'
// * RFC 4648 URI: '-' and '_'
// * RFC 3501: '+' and ','
//
// The resulting Encoding uses the default padding character ('='), which may
// be changed or disabled via WithPadding. The padding characters is urestricted,
// but it must be a character outside of the encoder alphabet.
func NewEncoding(encoder string) *Encoding {
if len(encoder) != 64 {
panic("encoding alphabet is not 64-bytes long")
}
if _, ok := allowedEncoding[encoder]; !ok {
panic("non-standard encoding alphabets are not supported")
}
return newEncoding(encoder)
}
var allowedEncoding = map[string]struct{}{
encodeStd: {},
encodeURL: {},
encodeIMAP: {},
}
+160
View File
@@ -0,0 +1,160 @@
//go:build amd64 && !purego
// +build amd64,!purego
package base64
import (
"encoding/base64"
"github.com/segmentio/asm/cpu"
"github.com/segmentio/asm/cpu/x86"
"github.com/segmentio/asm/internal/unsafebytes"
)
// An Encoding is a radix 64 encoding/decoding scheme, defined by a
// 64-character alphabet.
type Encoding struct {
enc func(dst []byte, src []byte, lut *int8) (int, int)
enclut [32]int8
dec func(dst []byte, src []byte, lut *int8) (int, int)
declut [48]int8
base *base64.Encoding
}
const (
minEncodeLen = 28
minDecodeLen = 45
)
func newEncoding(encoder string) *Encoding {
e := &Encoding{base: base64.NewEncoding(encoder)}
if cpu.X86.Has(x86.AVX2) {
e.enableEncodeAVX2(encoder)
e.enableDecodeAVX2(encoder)
}
return e
}
func (e *Encoding) enableEncodeAVX2(encoder string) {
// Translate values 0..63 to the Base64 alphabet. There are five sets:
//
// From To Add Index Example
// [0..25] [65..90] +65 0 ABCDEFGHIJKLMNOPQRSTUVWXYZ
// [26..51] [97..122] +71 1 abcdefghijklmnopqrstuvwxyz
// [52..61] [48..57] -4 [2..11] 0123456789
// [62] [43] -19 12 +
// [63] [47] -16 13 /
tab := [32]int8{int8(encoder[0]), int8(encoder[letterRange]) - letterRange}
for i, ch := range encoder[2*letterRange:] {
tab[2+i] = int8(ch) - 2*letterRange - int8(i)
}
e.enc = encodeAVX2
e.enclut = tab
}
func (e *Encoding) enableDecodeAVX2(encoder string) {
c62, c63 := int8(encoder[62]), int8(encoder[63])
url := c63 == '_'
if url {
c63 = '/'
}
// Translate values from the Base64 alphabet using five sets. Values outside
// of these ranges are considered invalid:
//
// From To Add Index Example
// [47] [63] +16 1 /
// [43] [62] +19 2 +
// [48..57] [52..61] +4 3 0123456789
// [65..90] [0..25] -65 4,5 ABCDEFGHIJKLMNOPQRSTUVWXYZ
// [97..122] [26..51] -71 6,7 abcdefghijklmnopqrstuvwxyz
tab := [48]int8{
0, 63 - c63, 62 - c62, 4, -65, -65, -71, -71,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x15, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x13, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B,
}
tab[(c62&15)+16] = 0x1A
tab[(c63&15)+16] = 0x1A
if url {
e.dec = decodeAVX2URI
} else {
e.dec = decodeAVX2
}
e.declut = tab
}
// WithPadding creates a duplicate Encoding updated with a specified padding
// character, or NoPadding to disable padding. The padding character must not
// be contained in the encoding alphabet, must not be '\r' or '\n', and must
// be no greater than '\xFF'.
func (enc Encoding) WithPadding(padding rune) *Encoding {
enc.base = enc.base.WithPadding(padding)
return &enc
}
// Strict creates a duplicate encoding updated with strict decoding enabled.
// This requires that trailing padding bits are zero.
func (enc Encoding) Strict() *Encoding {
enc.base = enc.base.Strict()
return &enc
}
// Encode encodes src using the defined encoding alphabet.
// This will write EncodedLen(len(src)) bytes to dst.
func (enc *Encoding) Encode(dst, src []byte) {
if len(src) >= minEncodeLen && enc.enc != nil {
d, s := enc.enc(dst, src, &enc.enclut[0])
dst = dst[d:]
src = src[s:]
}
enc.base.Encode(dst, src)
}
// Encode encodes src using the encoding enc, writing
// EncodedLen(len(src)) bytes to dst.
func (enc *Encoding) EncodeToString(src []byte) string {
buf := make([]byte, enc.base.EncodedLen(len(src)))
enc.Encode(buf, src)
return string(buf)
}
// EncodedLen calculates the base64-encoded byte length for a message
// of length n.
func (enc *Encoding) EncodedLen(n int) int {
return enc.base.EncodedLen(n)
}
// Decode decodes src using the defined encoding alphabet.
// This will write DecodedLen(len(src)) bytes to dst and return the number of
// bytes written.
func (enc *Encoding) Decode(dst, src []byte) (n int, err error) {
var d, s int
if len(src) >= minDecodeLen && enc.dec != nil {
d, s = enc.dec(dst, src, &enc.declut[0])
dst = dst[d:]
src = src[s:]
}
n, err = enc.base.Decode(dst, src)
n += d
return
}
// DecodeString decodes the base64 encoded string s, returns the decoded
// value as bytes.
func (enc *Encoding) DecodeString(s string) ([]byte, error) {
src := unsafebytes.BytesOf(s)
dst := make([]byte, enc.base.DecodedLen(len(s)))
n, err := enc.Decode(dst, src)
return dst[:n], err
}
// DecodedLen calculates the decoded byte length for a base64-encoded message
// of length n.
func (enc *Encoding) DecodedLen(n int) int {
return enc.base.DecodedLen(n)
}
+14
View File
@@ -0,0 +1,14 @@
//go:build purego || !amd64
// +build purego !amd64
package base64
import "encoding/base64"
// An Encoding is a radix 64 encoding/decoding scheme, defined by a
// 64-character alphabet.
type Encoding = base64.Encoding
func newEncoding(encoder string) *Encoding {
return base64.NewEncoding(encoder)
}
+10
View File
@@ -0,0 +1,10 @@
// Code generated by command: go run decode_asm.go -pkg base64 -out ../base64/decode_amd64.s -stubs ../base64/decode_amd64.go. DO NOT EDIT.
//go:build !purego
// +build !purego
package base64
func decodeAVX2(dst []byte, src []byte, lut *int8) (int, int)
func decodeAVX2URI(dst []byte, src []byte, lut *int8) (int, int)
+144
View File
@@ -0,0 +1,144 @@
// Code generated by command: go run decode_asm.go -pkg base64 -out ../base64/decode_amd64.s -stubs ../base64/decode_amd64.go. DO NOT EDIT.
//go:build !purego
// +build !purego
#include "textflag.h"
DATA b64_dec_lut_hi<>+0(SB)/8, $0x0804080402011010
DATA b64_dec_lut_hi<>+8(SB)/8, $0x1010101010101010
DATA b64_dec_lut_hi<>+16(SB)/8, $0x0804080402011010
DATA b64_dec_lut_hi<>+24(SB)/8, $0x1010101010101010
GLOBL b64_dec_lut_hi<>(SB), RODATA|NOPTR, $32
DATA b64_dec_madd1<>+0(SB)/8, $0x0140014001400140
DATA b64_dec_madd1<>+8(SB)/8, $0x0140014001400140
DATA b64_dec_madd1<>+16(SB)/8, $0x0140014001400140
DATA b64_dec_madd1<>+24(SB)/8, $0x0140014001400140
GLOBL b64_dec_madd1<>(SB), RODATA|NOPTR, $32
DATA b64_dec_madd2<>+0(SB)/8, $0x0001100000011000
DATA b64_dec_madd2<>+8(SB)/8, $0x0001100000011000
DATA b64_dec_madd2<>+16(SB)/8, $0x0001100000011000
DATA b64_dec_madd2<>+24(SB)/8, $0x0001100000011000
GLOBL b64_dec_madd2<>(SB), RODATA|NOPTR, $32
DATA b64_dec_shuf_lo<>+0(SB)/8, $0x0000000000000000
DATA b64_dec_shuf_lo<>+8(SB)/8, $0x0600010200000000
GLOBL b64_dec_shuf_lo<>(SB), RODATA|NOPTR, $16
DATA b64_dec_shuf<>+0(SB)/8, $0x090a040506000102
DATA b64_dec_shuf<>+8(SB)/8, $0x000000000c0d0e08
DATA b64_dec_shuf<>+16(SB)/8, $0x0c0d0e08090a0405
DATA b64_dec_shuf<>+24(SB)/8, $0x0000000000000000
GLOBL b64_dec_shuf<>(SB), RODATA|NOPTR, $32
// func decodeAVX2(dst []byte, src []byte, lut *int8) (int, int)
// Requires: AVX, AVX2, SSE4.1
TEXT ·decodeAVX2(SB), NOSPLIT, $0-72
MOVQ dst_base+0(FP), AX
MOVQ src_base+24(FP), DX
MOVQ lut+48(FP), SI
MOVQ src_len+32(FP), DI
MOVB $0x2f, CL
PINSRB $0x00, CX, X8
VPBROADCASTB X8, Y8
XORQ CX, CX
XORQ BX, BX
VPXOR Y7, Y7, Y7
VPERMQ $0x44, (SI), Y6
VPERMQ $0x44, 16(SI), Y4
VMOVDQA b64_dec_lut_hi<>+0(SB), Y5
loop:
VMOVDQU (DX)(BX*1), Y0
VPSRLD $0x04, Y0, Y2
VPAND Y8, Y0, Y3
VPSHUFB Y3, Y4, Y3
VPAND Y8, Y2, Y2
VPSHUFB Y2, Y5, Y9
VPTEST Y9, Y3
JNE done
VPCMPEQB Y8, Y0, Y3
VPADDB Y3, Y2, Y2
VPSHUFB Y2, Y6, Y2
VPADDB Y0, Y2, Y0
VPMADDUBSW b64_dec_madd1<>+0(SB), Y0, Y0
VPMADDWD b64_dec_madd2<>+0(SB), Y0, Y0
VEXTRACTI128 $0x01, Y0, X1
VPSHUFB b64_dec_shuf_lo<>+0(SB), X1, X1
VPSHUFB b64_dec_shuf<>+0(SB), Y0, Y0
VPBLENDD $0x08, Y1, Y0, Y1
VPBLENDD $0xc0, Y7, Y1, Y1
VMOVDQU Y1, (AX)(CX*1)
ADDQ $0x18, CX
ADDQ $0x20, BX
SUBQ $0x20, DI
CMPQ DI, $0x2d
JB done
JMP loop
done:
MOVQ CX, ret+56(FP)
MOVQ BX, ret1+64(FP)
VZEROUPPER
RET
// func decodeAVX2URI(dst []byte, src []byte, lut *int8) (int, int)
// Requires: AVX, AVX2, SSE4.1
TEXT ·decodeAVX2URI(SB), NOSPLIT, $0-72
MOVB $0x2f, AL
PINSRB $0x00, AX, X0
VPBROADCASTB X0, Y0
MOVB $0x5f, AL
PINSRB $0x00, AX, X1
VPBROADCASTB X1, Y1
MOVQ dst_base+0(FP), AX
MOVQ src_base+24(FP), DX
MOVQ lut+48(FP), SI
MOVQ src_len+32(FP), DI
MOVB $0x2f, CL
PINSRB $0x00, CX, X10
VPBROADCASTB X10, Y10
XORQ CX, CX
XORQ BX, BX
VPXOR Y9, Y9, Y9
VPERMQ $0x44, (SI), Y8
VPERMQ $0x44, 16(SI), Y6
VMOVDQA b64_dec_lut_hi<>+0(SB), Y7
loop:
VMOVDQU (DX)(BX*1), Y2
VPCMPEQB Y2, Y1, Y4
VPBLENDVB Y4, Y0, Y2, Y2
VPSRLD $0x04, Y2, Y4
VPAND Y10, Y2, Y5
VPSHUFB Y5, Y6, Y5
VPAND Y10, Y4, Y4
VPSHUFB Y4, Y7, Y11
VPTEST Y11, Y5
JNE done
VPCMPEQB Y10, Y2, Y5
VPADDB Y5, Y4, Y4
VPSHUFB Y4, Y8, Y4
VPADDB Y2, Y4, Y2
VPMADDUBSW b64_dec_madd1<>+0(SB), Y2, Y2
VPMADDWD b64_dec_madd2<>+0(SB), Y2, Y2
VEXTRACTI128 $0x01, Y2, X3
VPSHUFB b64_dec_shuf_lo<>+0(SB), X3, X3
VPSHUFB b64_dec_shuf<>+0(SB), Y2, Y2
VPBLENDD $0x08, Y3, Y2, Y3
VPBLENDD $0xc0, Y9, Y3, Y3
VMOVDQU Y3, (AX)(CX*1)
ADDQ $0x18, CX
ADDQ $0x20, BX
SUBQ $0x20, DI
CMPQ DI, $0x2d
JB done
JMP loop
done:
MOVQ CX, ret+56(FP)
MOVQ BX, ret1+64(FP)
VZEROUPPER
RET
+8
View File
@@ -0,0 +1,8 @@
// Code generated by command: go run encode_asm.go -pkg base64 -out ../base64/encode_amd64.s -stubs ../base64/encode_amd64.go. DO NOT EDIT.
//go:build !purego
// +build !purego
package base64
func encodeAVX2(dst []byte, src []byte, lut *int8) (int, int)
+88
View File
@@ -0,0 +1,88 @@
// Code generated by command: go run encode_asm.go -pkg base64 -out ../base64/encode_amd64.s -stubs ../base64/encode_amd64.go. DO NOT EDIT.
//go:build !purego
// +build !purego
#include "textflag.h"
// func encodeAVX2(dst []byte, src []byte, lut *int8) (int, int)
// Requires: AVX, AVX2, SSE4.1
TEXT ·encodeAVX2(SB), NOSPLIT, $0-72
MOVQ dst_base+0(FP), AX
MOVQ src_base+24(FP), DX
MOVQ lut+48(FP), SI
MOVQ src_len+32(FP), DI
MOVB $0x33, CL
PINSRB $0x00, CX, X4
VPBROADCASTB X4, Y4
MOVB $0x19, CL
PINSRB $0x00, CX, X5
VPBROADCASTB X5, Y5
XORQ CX, CX
XORQ BX, BX
// Load the 16-byte LUT into both lanes of the register
VPERMQ $0x44, (SI), Y3
// Load the first block using a mask to avoid potential fault
VMOVDQU b64_enc_load<>+0(SB), Y0
VPMASKMOVD -4(DX)(BX*1), Y0, Y0
loop:
VPSHUFB b64_enc_shuf<>+0(SB), Y0, Y0
VPAND b64_enc_mask1<>+0(SB), Y0, Y1
VPSLLW $0x08, Y1, Y2
VPSLLW $0x04, Y1, Y1
VPBLENDW $0xaa, Y2, Y1, Y2
VPAND b64_enc_mask2<>+0(SB), Y0, Y1
VPMULHUW b64_enc_mult<>+0(SB), Y1, Y0
VPOR Y0, Y2, Y0
VPSUBUSB Y4, Y0, Y1
VPCMPGTB Y5, Y0, Y2
VPSUBB Y2, Y1, Y1
VPSHUFB Y1, Y3, Y1
VPADDB Y0, Y1, Y0
VMOVDQU Y0, (AX)(CX*1)
ADDQ $0x20, CX
ADDQ $0x18, BX
SUBQ $0x18, DI
CMPQ DI, $0x20
JB done
VMOVDQU -4(DX)(BX*1), Y0
JMP loop
done:
MOVQ CX, ret+56(FP)
MOVQ BX, ret1+64(FP)
VZEROUPPER
RET
DATA b64_enc_load<>+0(SB)/8, $0x8000000000000000
DATA b64_enc_load<>+8(SB)/8, $0x8000000080000000
DATA b64_enc_load<>+16(SB)/8, $0x8000000080000000
DATA b64_enc_load<>+24(SB)/8, $0x8000000080000000
GLOBL b64_enc_load<>(SB), RODATA|NOPTR, $32
DATA b64_enc_shuf<>+0(SB)/8, $0x0809070805060405
DATA b64_enc_shuf<>+8(SB)/8, $0x0e0f0d0e0b0c0a0b
DATA b64_enc_shuf<>+16(SB)/8, $0x0405030401020001
DATA b64_enc_shuf<>+24(SB)/8, $0x0a0b090a07080607
GLOBL b64_enc_shuf<>(SB), RODATA|NOPTR, $32
DATA b64_enc_mask1<>+0(SB)/8, $0x003f03f0003f03f0
DATA b64_enc_mask1<>+8(SB)/8, $0x003f03f0003f03f0
DATA b64_enc_mask1<>+16(SB)/8, $0x003f03f0003f03f0
DATA b64_enc_mask1<>+24(SB)/8, $0x003f03f0003f03f0
GLOBL b64_enc_mask1<>(SB), RODATA|NOPTR, $32
DATA b64_enc_mask2<>+0(SB)/8, $0x0fc0fc000fc0fc00
DATA b64_enc_mask2<>+8(SB)/8, $0x0fc0fc000fc0fc00
DATA b64_enc_mask2<>+16(SB)/8, $0x0fc0fc000fc0fc00
DATA b64_enc_mask2<>+24(SB)/8, $0x0fc0fc000fc0fc00
GLOBL b64_enc_mask2<>(SB), RODATA|NOPTR, $32
DATA b64_enc_mult<>+0(SB)/8, $0x0400004004000040
DATA b64_enc_mult<>+8(SB)/8, $0x0400004004000040
DATA b64_enc_mult<>+16(SB)/8, $0x0400004004000040
DATA b64_enc_mult<>+24(SB)/8, $0x0400004004000040
GLOBL b64_enc_mult<>(SB), RODATA|NOPTR, $32
+80
View File
@@ -0,0 +1,80 @@
package arm
import (
"github.com/segmentio/asm/cpu/cpuid"
. "golang.org/x/sys/cpu"
)
type CPU cpuid.CPU
func (cpu CPU) Has(feature Feature) bool {
return cpuid.CPU(cpu).Has(cpuid.Feature(feature))
}
func (cpu *CPU) set(feature Feature, enable bool) {
(*cpuid.CPU)(cpu).Set(cpuid.Feature(feature), enable)
}
type Feature cpuid.Feature
const (
SWP Feature = 1 << iota // SWP instruction support
HALF // Half-word load and store support
THUMB // ARM Thumb instruction set
BIT26 // Address space limited to 26-bits
FASTMUL // 32-bit operand, 64-bit result multiplication support
FPA // Floating point arithmetic support
VFP // Vector floating point support
EDSP // DSP Extensions support
JAVA // Java instruction set
IWMMXT // Intel Wireless MMX technology support
CRUNCH // MaverickCrunch context switching and handling
THUMBEE // Thumb EE instruction set
NEON // NEON instruction set
VFPv3 // Vector floating point version 3 support
VFPv3D16 // Vector floating point version 3 D8-D15
TLS // Thread local storage support
VFPv4 // Vector floating point version 4 support
IDIVA // Integer divide instruction support in ARM mode
IDIVT // Integer divide instruction support in Thumb mode
VFPD32 // Vector floating point version 3 D15-D31
LPAE // Large Physical Address Extensions
EVTSTRM // Event stream support
AES // AES hardware implementation
PMULL // Polynomial multiplication instruction set
SHA1 // SHA1 hardware implementation
SHA2 // SHA2 hardware implementation
CRC32 // CRC32 hardware implementation
)
func ABI() CPU {
cpu := CPU(0)
cpu.set(SWP, ARM.HasSWP)
cpu.set(HALF, ARM.HasHALF)
cpu.set(THUMB, ARM.HasTHUMB)
cpu.set(BIT26, ARM.Has26BIT)
cpu.set(FASTMUL, ARM.HasFASTMUL)
cpu.set(FPA, ARM.HasFPA)
cpu.set(VFP, ARM.HasVFP)
cpu.set(EDSP, ARM.HasEDSP)
cpu.set(JAVA, ARM.HasJAVA)
cpu.set(IWMMXT, ARM.HasIWMMXT)
cpu.set(CRUNCH, ARM.HasCRUNCH)
cpu.set(THUMBEE, ARM.HasTHUMBEE)
cpu.set(NEON, ARM.HasNEON)
cpu.set(VFPv3, ARM.HasVFPv3)
cpu.set(VFPv3D16, ARM.HasVFPv3D16)
cpu.set(TLS, ARM.HasTLS)
cpu.set(VFPv4, ARM.HasVFPv4)
cpu.set(IDIVA, ARM.HasIDIVA)
cpu.set(IDIVT, ARM.HasIDIVT)
cpu.set(VFPD32, ARM.HasVFPD32)
cpu.set(LPAE, ARM.HasLPAE)
cpu.set(EVTSTRM, ARM.HasEVTSTRM)
cpu.set(AES, ARM.HasAES)
cpu.set(PMULL, ARM.HasPMULL)
cpu.set(SHA1, ARM.HasSHA1)
cpu.set(SHA2, ARM.HasSHA2)
cpu.set(CRC32, ARM.HasCRC32)
return cpu
}
+74
View File
@@ -0,0 +1,74 @@
package arm64
import (
"github.com/segmentio/asm/cpu/cpuid"
. "golang.org/x/sys/cpu"
)
type CPU cpuid.CPU
func (cpu CPU) Has(feature Feature) bool {
return cpuid.CPU(cpu).Has(cpuid.Feature(feature))
}
func (cpu *CPU) set(feature Feature, enable bool) {
(*cpuid.CPU)(cpu).Set(cpuid.Feature(feature), enable)
}
type Feature cpuid.Feature
const (
FP Feature = 1 << iota // Floating-point instruction set (always available)
ASIMD // Advanced SIMD (always available)
EVTSTRM // Event stream support
AES // AES hardware implementation
PMULL // Polynomial multiplication instruction set
SHA1 // SHA1 hardware implementation
SHA2 // SHA2 hardware implementation
CRC32 // CRC32 hardware implementation
ATOMICS // Atomic memory operation instruction set
FPHP // Half precision floating-point instruction set
ASIMDHP // Advanced SIMD half precision instruction set
CPUID // CPUID identification scheme registers
ASIMDRDM // Rounding double multiply add/subtract instruction set
JSCVT // Javascript conversion from floating-point to integer
FCMA // Floating-point multiplication and addition of complex numbers
LRCPC // Release Consistent processor consistent support
DCPOP // Persistent memory support
SHA3 // SHA3 hardware implementation
SM3 // SM3 hardware implementation
SM4 // SM4 hardware implementation
ASIMDDP // Advanced SIMD double precision instruction set
SHA512 // SHA512 hardware implementation
SVE // Scalable Vector Extensions
ASIMDFHM // Advanced SIMD multiplication FP16 to FP32
)
func ABI() CPU {
cpu := CPU(0)
cpu.set(FP, ARM64.HasFP)
cpu.set(ASIMD, ARM64.HasASIMD)
cpu.set(EVTSTRM, ARM64.HasEVTSTRM)
cpu.set(AES, ARM64.HasAES)
cpu.set(PMULL, ARM64.HasPMULL)
cpu.set(SHA1, ARM64.HasSHA1)
cpu.set(SHA2, ARM64.HasSHA2)
cpu.set(CRC32, ARM64.HasCRC32)
cpu.set(ATOMICS, ARM64.HasATOMICS)
cpu.set(FPHP, ARM64.HasFPHP)
cpu.set(ASIMDHP, ARM64.HasASIMDHP)
cpu.set(CPUID, ARM64.HasCPUID)
cpu.set(ASIMDRDM, ARM64.HasASIMDRDM)
cpu.set(JSCVT, ARM64.HasJSCVT)
cpu.set(FCMA, ARM64.HasFCMA)
cpu.set(LRCPC, ARM64.HasLRCPC)
cpu.set(DCPOP, ARM64.HasDCPOP)
cpu.set(SHA3, ARM64.HasSHA3)
cpu.set(SM3, ARM64.HasSM3)
cpu.set(SM4, ARM64.HasSM4)
cpu.set(ASIMDDP, ARM64.HasASIMDDP)
cpu.set(SHA512, ARM64.HasSHA512)
cpu.set(SVE, ARM64.HasSVE)
cpu.set(ASIMDFHM, ARM64.HasASIMDFHM)
return cpu
}
+22
View File
@@ -0,0 +1,22 @@
// Pakage cpu provides APIs to detect CPU features available at runtime.
package cpu
import (
"github.com/segmentio/asm/cpu/arm"
"github.com/segmentio/asm/cpu/arm64"
"github.com/segmentio/asm/cpu/x86"
)
var (
// X86 is the bitset representing the set of the x86 instruction sets are
// supported by the CPU.
X86 = x86.ABI()
// ARM is the bitset representing which parts of the arm instruction sets
// are supported by the CPU.
ARM = arm.ABI()
// ARM64 is the bitset representing which parts of the arm64 instruction
// sets are supported by the CPU.
ARM64 = arm64.ABI()
)
+32
View File
@@ -0,0 +1,32 @@
// Package cpuid provides generic types used to represent CPU features supported
// by the architecture.
package cpuid
// CPU is a bitset of feature flags representing the capabilities of various CPU
// architeectures that this package provides optimized assembly routines for.
//
// The intent is to provide a stable ABI between the Go code that generate the
// assembly, and the program that uses the library functions.
type CPU uint64
// Feature represents a single CPU feature.
type Feature uint64
const (
// None is a Feature value that has no CPU features enabled.
None Feature = 0
// All is a Feature value that has all CPU features enabled.
All Feature = 0xFFFFFFFFFFFFFFFF
)
func (cpu CPU) Has(feature Feature) bool {
return (Feature(cpu) & feature) == feature
}
func (cpu *CPU) Set(feature Feature, enabled bool) {
if enabled {
*cpu |= CPU(feature)
} else {
*cpu &= ^CPU(feature)
}
}
+76
View File
@@ -0,0 +1,76 @@
package x86
import (
"github.com/segmentio/asm/cpu/cpuid"
. "golang.org/x/sys/cpu"
)
type CPU cpuid.CPU
func (cpu CPU) Has(feature Feature) bool {
return cpuid.CPU(cpu).Has(cpuid.Feature(feature))
}
func (cpu *CPU) set(feature Feature, enable bool) {
(*cpuid.CPU)(cpu).Set(cpuid.Feature(feature), enable)
}
type Feature cpuid.Feature
const (
SSE Feature = 1 << iota // SSE functions
SSE2 // P4 SSE functions
SSE3 // Prescott SSE3 functions
SSE41 // Penryn SSE4.1 functions
SSE42 // Nehalem SSE4.2 functions
SSE4A // AMD Barcelona microarchitecture SSE4a instructions
SSSE3 // Conroe SSSE3 functions
AVX // AVX functions
AVX2 // AVX2 functions
AVX512BF16 // AVX-512 BFLOAT16 Instructions
AVX512BITALG // AVX-512 Bit Algorithms
AVX512BW // AVX-512 Byte and Word Instructions
AVX512CD // AVX-512 Conflict Detection Instructions
AVX512DQ // AVX-512 Doubleword and Quadword Instructions
AVX512ER // AVX-512 Exponential and Reciprocal Instructions
AVX512F // AVX-512 Foundation
AVX512IFMA // AVX-512 Integer Fused Multiply-Add Instructions
AVX512PF // AVX-512 Prefetch Instructions
AVX512VBMI // AVX-512 Vector Bit Manipulation Instructions
AVX512VBMI2 // AVX-512 Vector Bit Manipulation Instructions, Version 2
AVX512VL // AVX-512 Vector Length Extensions
AVX512VNNI // AVX-512 Vector Neural Network Instructions
AVX512VP2INTERSECT // AVX-512 Intersect for D/Q
AVX512VPOPCNTDQ // AVX-512 Vector Population Count Doubleword and Quadword
CMOV // Conditional move
)
func ABI() CPU {
cpu := CPU(0)
cpu.set(SSE, true) // TODO: golang.org/x/sys/cpu assumes all CPUs have SEE?
cpu.set(SSE2, X86.HasSSE2)
cpu.set(SSE3, X86.HasSSE3)
cpu.set(SSE41, X86.HasSSE41)
cpu.set(SSE42, X86.HasSSE42)
cpu.set(SSE4A, false) // TODO: add upstream support in golang.org/x/sys/cpu?
cpu.set(SSSE3, X86.HasSSSE3)
cpu.set(AVX, X86.HasAVX)
cpu.set(AVX2, X86.HasAVX2)
cpu.set(AVX512BF16, X86.HasAVX512BF16)
cpu.set(AVX512BITALG, X86.HasAVX512BITALG)
cpu.set(AVX512BW, X86.HasAVX512BW)
cpu.set(AVX512CD, X86.HasAVX512CD)
cpu.set(AVX512DQ, X86.HasAVX512DQ)
cpu.set(AVX512ER, X86.HasAVX512ER)
cpu.set(AVX512F, X86.HasAVX512F)
cpu.set(AVX512IFMA, X86.HasAVX512IFMA)
cpu.set(AVX512PF, X86.HasAVX512PF)
cpu.set(AVX512VBMI, X86.HasAVX512VBMI)
cpu.set(AVX512VBMI2, X86.HasAVX512VBMI2)
cpu.set(AVX512VL, X86.HasAVX512VL)
cpu.set(AVX512VNNI, X86.HasAVX512VNNI)
cpu.set(AVX512VP2INTERSECT, false) // TODO: add upstream support in golang.org/x/sys/cpu?
cpu.set(AVX512VPOPCNTDQ, X86.HasAVX512VPOPCNTDQ)
cpu.set(CMOV, true) // TODO: golang.org/x/sys/cpu assumes all CPUs have CMOV?
return cpu
}
+20
View File
@@ -0,0 +1,20 @@
package unsafebytes
import "unsafe"
func Pointer(b []byte) *byte {
return *(**byte)(unsafe.Pointer(&b))
}
func String(b []byte) string {
return *(*string)(unsafe.Pointer(&b))
}
func BytesOf(s string) []byte {
return *(*[]byte)(unsafe.Pointer(&sliceHeader{str: s, cap: len(s)}))
}
type sliceHeader struct {
str string
cap int
}
+40
View File
@@ -0,0 +1,40 @@
package keyset
import (
"bytes"
"github.com/segmentio/asm/cpu"
"github.com/segmentio/asm/cpu/arm64"
"github.com/segmentio/asm/cpu/x86"
)
// New prepares a set of keys for use with Lookup.
//
// An optimized routine is used if the processor supports AVX instructions and
// the maximum length of any of the keys is less than or equal to 16. If New
// returns nil, this indicates that an optimized routine is not available, and
// the caller should use a fallback.
func New(keys [][]byte) []byte {
maxWidth, hasNullByte := checkKeys(keys)
if hasNullByte || maxWidth > 16 || !(cpu.X86.Has(x86.AVX) || cpu.ARM64.Has(arm64.ASIMD)) {
return nil
}
set := make([]byte, len(keys)*16)
for i, k := range keys {
copy(set[i*16:], k)
}
return set
}
func checkKeys(keys [][]byte) (maxWidth int, hasNullByte bool) {
for _, k := range keys {
if len(k) > maxWidth {
maxWidth = len(k)
}
if bytes.IndexByte(k, 0) >= 0 {
hasNullByte = true
}
}
return
}
+10
View File
@@ -0,0 +1,10 @@
// Code generated by command: go run keyset_asm.go -pkg keyset -out ../keyset/keyset_amd64.s -stubs ../keyset/keyset_amd64.go. DO NOT EDIT.
//go:build !purego
// +build !purego
package keyset
// Lookup searches for a key in a set of keys, returning its index if
// found. If the key cannot be found, the number of keys is returned.
func Lookup(keyset []byte, key []byte) int
+108
View File
@@ -0,0 +1,108 @@
// Code generated by command: go run keyset_asm.go -pkg keyset -out ../keyset/keyset_amd64.s -stubs ../keyset/keyset_amd64.go. DO NOT EDIT.
//go:build !purego
// +build !purego
#include "textflag.h"
// func Lookup(keyset []byte, key []byte) int
// Requires: AVX
TEXT ·Lookup(SB), NOSPLIT, $0-56
MOVQ keyset_base+0(FP), AX
MOVQ keyset_len+8(FP), CX
SHRQ $0x04, CX
MOVQ key_base+24(FP), DX
MOVQ key_len+32(FP), BX
MOVQ key_cap+40(FP), SI
CMPQ BX, $0x10
JA not_found
CMPQ SI, $0x10
JB safe_load
load:
VMOVUPS (DX), X0
prepare:
VPXOR X2, X2, X2
VPCMPEQB X1, X1, X1
LEAQ blend_masks<>+16(SB), DX
SUBQ BX, DX
VMOVUPS (DX), X3
VPBLENDVB X3, X0, X2, X0
XORQ DX, DX
MOVQ CX, BX
SHRQ $0x02, BX
SHLQ $0x02, BX
bigloop:
CMPQ DX, BX
JE loop
VPCMPEQB (AX), X0, X8
VPTEST X1, X8
JCS done
VPCMPEQB 16(AX), X0, X9
VPTEST X1, X9
JCS found1
VPCMPEQB 32(AX), X0, X10
VPTEST X1, X10
JCS found2
VPCMPEQB 48(AX), X0, X11
VPTEST X1, X11
JCS found3
ADDQ $0x04, DX
ADDQ $0x40, AX
JMP bigloop
loop:
CMPQ DX, CX
JE done
VPCMPEQB (AX), X0, X2
VPTEST X1, X2
JCS done
INCQ DX
ADDQ $0x10, AX
JMP loop
JMP done
found3:
INCQ DX
found2:
INCQ DX
found1:
INCQ DX
done:
MOVQ DX, ret+48(FP)
RET
not_found:
MOVQ CX, ret+48(FP)
RET
safe_load:
MOVQ DX, SI
ANDQ $0x00000fff, SI
CMPQ SI, $0x00000ff0
JBE load
MOVQ $0xfffffffffffffff0, SI
ADDQ BX, SI
VMOVUPS (DX)(SI*1), X0
LEAQ shuffle_masks<>+16(SB), DX
SUBQ BX, DX
VMOVUPS (DX), X1
VPSHUFB X1, X0, X0
JMP prepare
DATA blend_masks<>+0(SB)/8, $0xffffffffffffffff
DATA blend_masks<>+8(SB)/8, $0xffffffffffffffff
DATA blend_masks<>+16(SB)/8, $0x0000000000000000
DATA blend_masks<>+24(SB)/8, $0x0000000000000000
GLOBL blend_masks<>(SB), RODATA|NOPTR, $32
DATA shuffle_masks<>+0(SB)/8, $0x0706050403020100
DATA shuffle_masks<>+8(SB)/8, $0x0f0e0d0c0b0a0908
DATA shuffle_masks<>+16(SB)/8, $0x0706050403020100
DATA shuffle_masks<>+24(SB)/8, $0x0f0e0d0c0b0a0908
GLOBL shuffle_masks<>(SB), RODATA|NOPTR, $32
+8
View File
@@ -0,0 +1,8 @@
//go:build !purego
// +build !purego
package keyset
// Lookup searches for a key in a set of keys, returning its index if
// found. If the key cannot be found, the number of keys is returned.
func Lookup(keyset []byte, key []byte) int
+143
View File
@@ -0,0 +1,143 @@
//go:build !purego
// +build !purego
#include "textflag.h"
// func Lookup(keyset []byte, key []byte) int
TEXT ·Lookup(SB), NOSPLIT, $0-56
MOVD keyset+0(FP), R0
MOVD keyset_len+8(FP), R1
MOVD key+24(FP), R2
MOVD key_len+32(FP), R3
MOVD key_cap+40(FP), R4
// None of the keys in the set are greater than 16 bytes, so if the input
// key is we can jump straight to not found.
CMP $16, R3
BHI notfound
// We'll be moving the keyset pointer (R0) forward as we compare keys, so
// make a copy of the starting point (R6). Also add the byte length (R1) to
// obtain a pointer to the end of the keyset (R5).
MOVD R0, R6
ADD R0, R1, R5
// Prepare a 64-bit mask of all ones.
MOVD $-1, R7
// Prepare a vector of all zeroes.
VMOV ZR, V1.B16
// Check that it's safe to load 16 bytes of input. If cap(input)<16, jump
// to a check that determines whether a tail load is necessary (to avoid a
// page fault).
CMP $16, R4
BLO safeload
load:
// Load the input key (V0) and pad with zero bytes (V1). To blend the two
// vectors, we load a mask for the particular key length and then use TBL
// to select bytes from either V0 or V1.
VLD1 (R2), [V0.B16]
MOVD $blend_masks<>(SB), R10
ADD R3<<4, R10, R10
VLD1 (R10), [V2.B16]
VTBL V2.B16, [V0.B16, V1.B16], V3.B16
loop:
// Loop through each 16 byte key in the keyset.
CMP R0, R5
BEQ notfound
// Load and compare the next key.
VLD1.P 16(R0), [V4.B16]
VCMEQ V3.B16, V4.B16, V5.B16
VMOV V5.D[0], R8
VMOV V5.D[1], R9
AND R8, R9, R9
// If the masks match, we found the key.
CMP R9, R7
BEQ found
JMP loop
found:
// If the key was found, take the position in the keyset and convert it
// to an index. The keyset pointer (R0) will be 1 key past the match, so
// subtract the starting pointer (R6), divide by 16 to convert from byte
// length to an index, and then subtract one.
SUB R6, R0, R0
ADD R0>>4, ZR, R0
SUB $1, R0, R0
MOVD R0, ret+48(FP)
RET
notfound:
// Return the number of keys in the keyset, which is the byte length (R1)
// divided by 16.
ADD R1>>4, ZR, R1
MOVD R1, ret+48(FP)
RET
safeload:
// Check if the input crosses a page boundary. If not, jump back.
AND $4095, R2, R12
CMP $4080, R12
BLS load
// If it does cross a page boundary, we must assume that loading 16 bytes
// will cause a fault. Instead, we load the 16 bytes up to and including the
// key and then shuffle the key forward in the register. We can shuffle and
// pad with zeroes at the same time to avoid having to also blend (as load
// does).
MOVD $16, R12
SUB R3, R12, R12
SUB R12, R2, R2
VLD1 (R2), [V0.B16]
MOVD $shuffle_masks<>(SB), R10
ADD R12, R10, R10
VLD1 (R10), [V2.B16]
VTBL V2.B16, [V0.B16, V1.B16], V3.B16
JMP loop
DATA blend_masks<>+0(SB)/8, $0x1010101010101010
DATA blend_masks<>+8(SB)/8, $0x1010101010101010
DATA blend_masks<>+16(SB)/8, $0x1010101010101000
DATA blend_masks<>+24(SB)/8, $0x1010101010101010
DATA blend_masks<>+32(SB)/8, $0x1010101010100100
DATA blend_masks<>+40(SB)/8, $0x1010101010101010
DATA blend_masks<>+48(SB)/8, $0x1010101010020100
DATA blend_masks<>+56(SB)/8, $0x1010101010101010
DATA blend_masks<>+64(SB)/8, $0x1010101003020100
DATA blend_masks<>+72(SB)/8, $0x1010101010101010
DATA blend_masks<>+80(SB)/8, $0x1010100403020100
DATA blend_masks<>+88(SB)/8, $0x1010101010101010
DATA blend_masks<>+96(SB)/8, $0x1010050403020100
DATA blend_masks<>+104(SB)/8, $0x1010101010101010
DATA blend_masks<>+112(SB)/8, $0x1006050403020100
DATA blend_masks<>+120(SB)/8, $0x1010101010101010
DATA blend_masks<>+128(SB)/8, $0x0706050403020100
DATA blend_masks<>+136(SB)/8, $0x1010101010101010
DATA blend_masks<>+144(SB)/8, $0x0706050403020100
DATA blend_masks<>+152(SB)/8, $0x1010101010101008
DATA blend_masks<>+160(SB)/8, $0x0706050403020100
DATA blend_masks<>+168(SB)/8, $0x1010101010100908
DATA blend_masks<>+176(SB)/8, $0x0706050403020100
DATA blend_masks<>+184(SB)/8, $0x10101010100A0908
DATA blend_masks<>+192(SB)/8, $0x0706050403020100
DATA blend_masks<>+200(SB)/8, $0x101010100B0A0908
DATA blend_masks<>+208(SB)/8, $0x0706050403020100
DATA blend_masks<>+216(SB)/8, $0x1010100C0B0A0908
DATA blend_masks<>+224(SB)/8, $0x0706050403020100
DATA blend_masks<>+232(SB)/8, $0x10100D0C0B0A0908
DATA blend_masks<>+240(SB)/8, $0x0706050403020100
DATA blend_masks<>+248(SB)/8, $0x100E0D0C0B0A0908
DATA blend_masks<>+256(SB)/8, $0x0706050403020100
DATA blend_masks<>+264(SB)/8, $0x0F0E0D0C0B0A0908
GLOBL blend_masks<>(SB), RODATA|NOPTR, $272
DATA shuffle_masks<>+0(SB)/8, $0x0706050403020100
DATA shuffle_masks<>+8(SB)/8, $0x0F0E0D0C0B0A0908
DATA shuffle_masks<>+16(SB)/8, $0x1010101010101010
DATA shuffle_masks<>+24(SB)/8, $0x1010101010101010
GLOBL shuffle_masks<>(SB), RODATA|NOPTR, $32
+19
View File
@@ -0,0 +1,19 @@
//go:build purego || !(amd64 || arm64)
// +build purego !amd64,!arm64
package keyset
func Lookup(keyset []byte, key []byte) int {
if len(key) > 16 {
return len(keyset) / 16
}
var padded [16]byte
copy(padded[:], key)
for i := 0; i < len(keyset); i += 16 {
if string(padded[:]) == string(keyset[i:i+16]) {
return i / 16
}
}
return len(keyset) / 16
}