diff --git a/base64_arm64.go b/base64_arm64.go index fd8cc70..3ccc13e 100644 --- a/base64_arm64.go +++ b/base64_arm64.go @@ -30,6 +30,11 @@ func encodeAsm(dst, src []byte, lut *[64]byte) int //go:noescape func decodeAsm(dst, src []byte, lut *[128]byte) int +// If cond is 0, sets res = b, otherwise sets res = a. +// +//go:noescape +func moveCond(res, a, b *byte, cond int) + func encode(enc *Encoding, dst, src []byte) { if len(src) >= 48 { encoded := encodeAsm(dst, src, &enc.encode) diff --git a/base64_arm64.s b/base64_arm64.s index f76a6e9..92e346f 100644 --- a/base64_arm64.s +++ b/base64_arm64.s @@ -131,3 +131,23 @@ loop: done: MOVD R2, ret+56(FP) RET + +// func moveCond(res, a, b *byte, cond int) +// If cond == 0 res=b, else res=a +TEXT ·moveCond(SB),NOSPLIT,$0 + MOVD res+0(FP), R0 + MOVD a+8(FP), R1 + MOVD b+16(FP), R2 + MOVD cond+24(FP), R3 + + VEOR V0.B16, V0.B16, V0.B16 + VMOV R3, V1.S4 + VCMEQ V0.S4, V1.S4, V2.S4 + + VLD1 (R1), [V3.B16] + VLD1 (R2), [V4.B16] + + VBSL V4.B16, V3.B16, V2.B16 + + VST1 [V2.B16], (R0) + RET diff --git a/base64_arm64_test.go b/base64_arm64_test.go index 2294f4b..f28d91e 100644 --- a/base64_arm64_test.go +++ b/base64_arm64_test.go @@ -90,3 +90,17 @@ func TestUrlDecodeSIMD(t *testing.T) { } } } + +func TestMoveCond(t *testing.T) { + a := []byte{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15} + b := []byte{15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0} + c := make([]byte, 16) + moveCond(&c[0], &a[0], &b[0], 0) + if (!bytes.Equal(c, b)) { + t.Errorf("expected %x, got %x", b, c) + } + moveCond(&c[0], &a[0], &b[0], 1) + if (!bytes.Equal(c, a)) { + t.Errorf("expected %x, got %x", a, c) + } +}