|
|
@@ -0,0 +1,668 @@
|
|
|
+// Copyright 2019 The Go Authors. All rights reserved.
|
|
|
+// Use of this source code is governed by a BSD-style
|
|
|
+// license that can be found in the LICENSE file.
|
|
|
+
|
|
|
+// Based on CRYPTOGAMS code with the following comment:
|
|
|
+// # ====================================================================
|
|
|
+// # Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
|
|
|
+// # project. The module is, however, dual licensed under OpenSSL and
|
|
|
+// # CRYPTOGAMS licenses depending on where you obtain it. For further
|
|
|
+// # details see http://www.openssl.org/~appro/cryptogams/.
|
|
|
+// # ====================================================================
|
|
|
+
|
|
|
+// Original code can be found at the link below:
|
|
|
+// https://github.com/dot-asm/cryptogams/commit/a60f5b50ed908e91e5c39ca79126a4a876d5d8ff
|
|
|
+
|
|
|
+// There are some differences between CRYPTOGAMS code and this one. The round
|
|
|
+// loop for "_int" isn't the same as the original. Some adjustments were
|
|
|
+// necessary because there are less vector registers available. For example, some
|
|
|
+// X variables (r12, r13, r14, and r15) share the same register used by the
|
|
|
+// counter. The original code uses ctr to name the counter. Here we use CNT
|
|
|
+// because golang uses CTR as the counter register name.
|
|
|
+
|
|
|
+// +build ppc64le,!gccgo,!appengine
|
|
|
+
|
|
|
+#include "textflag.h"
|
|
|
+
|
|
|
+#define OUT R3
|
|
|
+#define INP R4
|
|
|
+#define LEN R5
|
|
|
+#define KEY R6
|
|
|
+#define CNT R7
|
|
|
+
|
|
|
+#define TEMP R8
|
|
|
+
|
|
|
+#define X0 R11
|
|
|
+#define X1 R12
|
|
|
+#define X2 R14
|
|
|
+#define X3 R15
|
|
|
+#define X4 R16
|
|
|
+#define X5 R17
|
|
|
+#define X6 R18
|
|
|
+#define X7 R19
|
|
|
+#define X8 R20
|
|
|
+#define X9 R21
|
|
|
+#define X10 R22
|
|
|
+#define X11 R23
|
|
|
+#define X12 R24
|
|
|
+#define X13 R25
|
|
|
+#define X14 R26
|
|
|
+#define X15 R27
|
|
|
+
|
|
|
+#define CON0 X0
|
|
|
+#define CON1 X1
|
|
|
+#define CON2 X2
|
|
|
+#define CON3 X3
|
|
|
+
|
|
|
+#define KEY0 X4
|
|
|
+#define KEY1 X5
|
|
|
+#define KEY2 X6
|
|
|
+#define KEY3 X7
|
|
|
+#define KEY4 X8
|
|
|
+#define KEY5 X9
|
|
|
+#define KEY6 X10
|
|
|
+#define KEY7 X11
|
|
|
+
|
|
|
+#define CNT0 X12
|
|
|
+#define CNT1 X13
|
|
|
+#define CNT2 X14
|
|
|
+#define CNT3 X15
|
|
|
+
|
|
|
+#define TMP0 R9
|
|
|
+#define TMP1 R10
|
|
|
+#define TMP2 R28
|
|
|
+#define TMP3 R29
|
|
|
+
|
|
|
+#define CONSTS R8
|
|
|
+
|
|
|
+#define A0 V0
|
|
|
+#define B0 V1
|
|
|
+#define C0 V2
|
|
|
+#define D0 V3
|
|
|
+#define A1 V4
|
|
|
+#define B1 V5
|
|
|
+#define C1 V6
|
|
|
+#define D1 V7
|
|
|
+#define A2 V8
|
|
|
+#define B2 V9
|
|
|
+#define C2 V10
|
|
|
+#define D2 V11
|
|
|
+#define T0 V12
|
|
|
+#define T1 V13
|
|
|
+#define T2 V14
|
|
|
+
|
|
|
+#define K0 V15
|
|
|
+#define K1 V16
|
|
|
+#define K2 V17
|
|
|
+#define K3 V18
|
|
|
+#define K4 V19
|
|
|
+#define K5 V20
|
|
|
+
|
|
|
+#define FOUR V21
|
|
|
+#define SIXTEEN V22
|
|
|
+#define TWENTY4 V23
|
|
|
+#define TWENTY V24
|
|
|
+#define TWELVE V25
|
|
|
+#define TWENTY5 V26
|
|
|
+#define SEVEN V27
|
|
|
+
|
|
|
+#define INPPERM V28
|
|
|
+#define OUTPERM V29
|
|
|
+#define OUTMASK V30
|
|
|
+
|
|
|
+#define DD0 V31
|
|
|
+#define DD1 SEVEN
|
|
|
+#define DD2 T0
|
|
|
+#define DD3 T1
|
|
|
+#define DD4 T2
|
|
|
+
|
|
|
+DATA ·consts+0x00(SB)/8, $0x3320646e61707865
|
|
|
+DATA ·consts+0x08(SB)/8, $0x6b20657479622d32
|
|
|
+DATA ·consts+0x10(SB)/8, $0x0000000000000001
|
|
|
+DATA ·consts+0x18(SB)/8, $0x0000000000000000
|
|
|
+DATA ·consts+0x20(SB)/8, $0x0000000000000004
|
|
|
+DATA ·consts+0x28(SB)/8, $0x0000000000000000
|
|
|
+DATA ·consts+0x30(SB)/8, $0x0a0b08090e0f0c0d
|
|
|
+DATA ·consts+0x38(SB)/8, $0x0203000106070405
|
|
|
+DATA ·consts+0x40(SB)/8, $0x090a0b080d0e0f0c
|
|
|
+DATA ·consts+0x48(SB)/8, $0x0102030005060704
|
|
|
+GLOBL ·consts(SB), RODATA, $80
|
|
|
+
|
|
|
+//func chaCha20_ctr32_vmx(out, inp *byte, len int, key *[32]byte, counter *[16]byte)
|
|
|
+TEXT ·chaCha20_ctr32_vmx(SB),NOSPLIT|NOFRAME,$0
|
|
|
+ // Load the arguments inside the registers
|
|
|
+ MOVD out+0(FP), OUT
|
|
|
+ MOVD inp+8(FP), INP
|
|
|
+ MOVD len+16(FP), LEN
|
|
|
+ MOVD key+24(FP), KEY
|
|
|
+ MOVD cnt+32(FP), CNT
|
|
|
+
|
|
|
+ MOVD $·consts(SB), CONSTS // point to consts addr
|
|
|
+
|
|
|
+ MOVD $16, X0
|
|
|
+ MOVD $32, X1
|
|
|
+ MOVD $48, X2
|
|
|
+ MOVD $64, X3
|
|
|
+ MOVD $31, X4
|
|
|
+ MOVD $15, X5
|
|
|
+
|
|
|
+ // Load key
|
|
|
+ LVX (KEY)(R0), K1
|
|
|
+ LVSR (KEY)(R0), T0
|
|
|
+ LVX (KEY)(X0), K2
|
|
|
+ LVX (KEY)(X4), DD0
|
|
|
+
|
|
|
+ // Load counter
|
|
|
+ LVX (CNT)(R0), K3
|
|
|
+ LVSR (CNT)(R0), T1
|
|
|
+ LVX (CNT)(X5), DD1
|
|
|
+
|
|
|
+ // Load constants
|
|
|
+ LVX (CONSTS)(R0), K0
|
|
|
+ LVX (CONSTS)(X0), K5
|
|
|
+ LVX (CONSTS)(X1), FOUR
|
|
|
+ LVX (CONSTS)(X2), SIXTEEN
|
|
|
+ LVX (CONSTS)(X3), TWENTY4
|
|
|
+
|
|
|
+ // Align key and counter
|
|
|
+ VPERM K2, K1, T0, K1
|
|
|
+ VPERM DD0, K2, T0, K2
|
|
|
+ VPERM DD1, K3, T1, K3
|
|
|
+
|
|
|
+ // Load counter to GPR
|
|
|
+ MOVWZ 0(CNT), CNT0
|
|
|
+ MOVWZ 4(CNT), CNT1
|
|
|
+ MOVWZ 8(CNT), CNT2
|
|
|
+ MOVWZ 12(CNT), CNT3
|
|
|
+
|
|
|
+ // Adjust vectors for the initial state
|
|
|
+ VADDUWM K3, K5, K3
|
|
|
+ VADDUWM K3, K5, K4
|
|
|
+ VADDUWM K4, K5, K5
|
|
|
+
|
|
|
+ // Synthesized constants
|
|
|
+ VSPLTISW $-12, TWENTY
|
|
|
+ VSPLTISW $12, TWELVE
|
|
|
+ VSPLTISW $-7, TWENTY5
|
|
|
+
|
|
|
+ VXOR T0, T0, T0
|
|
|
+ VSPLTISW $-1, OUTMASK
|
|
|
+ LVSR (INP)(R0), INPPERM
|
|
|
+ LVSL (OUT)(R0), OUTPERM
|
|
|
+ VPERM OUTMASK, T0, OUTPERM, OUTMASK
|
|
|
+
|
|
|
+loop_outer_vmx:
|
|
|
+ // Load constant
|
|
|
+ MOVD $0x61707865, CON0
|
|
|
+ MOVD $0x3320646e, CON1
|
|
|
+ MOVD $0x79622d32, CON2
|
|
|
+ MOVD $0x6b206574, CON3
|
|
|
+
|
|
|
+ VOR K0, K0, A0
|
|
|
+ VOR K0, K0, A1
|
|
|
+ VOR K0, K0, A2
|
|
|
+ VOR K1, K1, B0
|
|
|
+
|
|
|
+ MOVD $10, TEMP
|
|
|
+
|
|
|
+ // Load key to GPR
|
|
|
+ MOVWZ 0(KEY), X4
|
|
|
+ MOVWZ 4(KEY), X5
|
|
|
+ MOVWZ 8(KEY), X6
|
|
|
+ MOVWZ 12(KEY), X7
|
|
|
+ VOR K1, K1, B1
|
|
|
+ VOR K1, K1, B2
|
|
|
+ MOVWZ 16(KEY), X8
|
|
|
+ MOVWZ 0(CNT), X12
|
|
|
+ MOVWZ 20(KEY), X9
|
|
|
+ MOVWZ 4(CNT), X13
|
|
|
+ VOR K2, K2, C0
|
|
|
+ VOR K2, K2, C1
|
|
|
+ MOVWZ 24(KEY), X10
|
|
|
+ MOVWZ 8(CNT), X14
|
|
|
+ VOR K2, K2, C2
|
|
|
+ VOR K3, K3, D0
|
|
|
+ MOVWZ 28(KEY), X11
|
|
|
+ MOVWZ 12(CNT), X15
|
|
|
+ VOR K4, K4, D1
|
|
|
+ VOR K5, K5, D2
|
|
|
+
|
|
|
+ MOVD X4, TMP0
|
|
|
+ MOVD X5, TMP1
|
|
|
+ MOVD X6, TMP2
|
|
|
+ MOVD X7, TMP3
|
|
|
+ VSPLTISW $7, SEVEN
|
|
|
+
|
|
|
+ MOVD TEMP, CTR
|
|
|
+
|
|
|
+loop_vmx:
|
|
|
+ // CRYPTOGAMS uses a macro to create a loop using perl. This isn't possible
|
|
|
+ // using assembly macros. Therefore, the macro expansion result was used
|
|
|
+ // in order to maintain the algorithm efficiency.
|
|
|
+ // This loop generates three keystream blocks using VMX instructions and,
|
|
|
+ // in parallel, one keystream block using scalar instructions.
|
|
|
+ ADD X4, X0, X0
|
|
|
+ ADD X5, X1, X1
|
|
|
+ VADDUWM A0, B0, A0
|
|
|
+ VADDUWM A1, B1, A1
|
|
|
+ ADD X6, X2, X2
|
|
|
+ ADD X7, X3, X3
|
|
|
+ VADDUWM A2, B2, A2
|
|
|
+ VXOR D0, A0, D0
|
|
|
+ XOR X0, X12, X12
|
|
|
+ XOR X1, X13, X13
|
|
|
+ VXOR D1, A1, D1
|
|
|
+ VXOR D2, A2, D2
|
|
|
+ XOR X2, X14, X14
|
|
|
+ XOR X3, X15, X15
|
|
|
+ VPERM D0, D0, SIXTEEN, D0
|
|
|
+ VPERM D1, D1, SIXTEEN, D1
|
|
|
+ ROTLW $16, X12, X12
|
|
|
+ ROTLW $16, X13, X13
|
|
|
+ VPERM D2, D2, SIXTEEN, D2
|
|
|
+ VADDUWM C0, D0, C0
|
|
|
+ ROTLW $16, X14, X14
|
|
|
+ ROTLW $16, X15, X15
|
|
|
+ VADDUWM C1, D1, C1
|
|
|
+ VADDUWM C2, D2, C2
|
|
|
+ ADD X12, X8, X8
|
|
|
+ ADD X13, X9, X9
|
|
|
+ VXOR B0, C0, T0
|
|
|
+ VXOR B1, C1, T1
|
|
|
+ ADD X14, X10, X10
|
|
|
+ ADD X15, X11, X11
|
|
|
+ VXOR B2, C2, T2
|
|
|
+ VRLW T0, TWELVE, B0
|
|
|
+ XOR X8, X4, X4
|
|
|
+ XOR X9, X5, X5
|
|
|
+ VRLW T1, TWELVE, B1
|
|
|
+ VRLW T2, TWELVE, B2
|
|
|
+ XOR X10, X6, X6
|
|
|
+ XOR X11, X7, X7
|
|
|
+ VADDUWM A0, B0, A0
|
|
|
+ VADDUWM A1, B1, A1
|
|
|
+ ROTLW $12, X4, X4
|
|
|
+ ROTLW $12, X5, X5
|
|
|
+ VADDUWM A2, B2, A2
|
|
|
+ VXOR D0, A0, D0
|
|
|
+ ROTLW $12, X6, X6
|
|
|
+ ROTLW $12, X7, X7
|
|
|
+ VXOR D1, A1, D1
|
|
|
+ VXOR D2, A2, D2
|
|
|
+ ADD X4, X0, X0
|
|
|
+ ADD X5, X1, X1
|
|
|
+ VPERM D0, D0, TWENTY4, D0
|
|
|
+ VPERM D1, D1, TWENTY4, D1
|
|
|
+ ADD X6, X2, X2
|
|
|
+ ADD X7, X3, X3
|
|
|
+ VPERM D2, D2, TWENTY4, D2
|
|
|
+ VADDUWM C0, D0, C0
|
|
|
+ XOR X0, X12, X12
|
|
|
+ XOR X1, X13, X13
|
|
|
+ VADDUWM C1, D1, C1
|
|
|
+ VADDUWM C2, D2, C2
|
|
|
+ XOR X2, X14, X14
|
|
|
+ XOR X3, X15, X15
|
|
|
+ VXOR B0, C0, T0
|
|
|
+ VXOR B1, C1, T1
|
|
|
+ ROTLW $8, X12, X12
|
|
|
+ ROTLW $8, X13, X13
|
|
|
+ VXOR B2, C2, T2
|
|
|
+ VRLW T0, SEVEN, B0
|
|
|
+ ROTLW $8, X14, X14
|
|
|
+ ROTLW $8, X15, X15
|
|
|
+ VRLW T1, SEVEN, B1
|
|
|
+ VRLW T2, SEVEN, B2
|
|
|
+ ADD X12, X8, X8
|
|
|
+ ADD X13, X9, X9
|
|
|
+ VSLDOI $8, C0, C0, C0
|
|
|
+ VSLDOI $8, C1, C1, C1
|
|
|
+ ADD X14, X10, X10
|
|
|
+ ADD X15, X11, X11
|
|
|
+ VSLDOI $8, C2, C2, C2
|
|
|
+ VSLDOI $12, B0, B0, B0
|
|
|
+ XOR X8, X4, X4
|
|
|
+ XOR X9, X5, X5
|
|
|
+ VSLDOI $12, B1, B1, B1
|
|
|
+ VSLDOI $12, B2, B2, B2
|
|
|
+ XOR X10, X6, X6
|
|
|
+ XOR X11, X7, X7
|
|
|
+ VSLDOI $4, D0, D0, D0
|
|
|
+ VSLDOI $4, D1, D1, D1
|
|
|
+ ROTLW $7, X4, X4
|
|
|
+ ROTLW $7, X5, X5
|
|
|
+ VSLDOI $4, D2, D2, D2
|
|
|
+ VADDUWM A0, B0, A0
|
|
|
+ ROTLW $7, X6, X6
|
|
|
+ ROTLW $7, X7, X7
|
|
|
+ VADDUWM A1, B1, A1
|
|
|
+ VADDUWM A2, B2, A2
|
|
|
+ ADD X5, X0, X0
|
|
|
+ ADD X6, X1, X1
|
|
|
+ VXOR D0, A0, D0
|
|
|
+ VXOR D1, A1, D1
|
|
|
+ ADD X7, X2, X2
|
|
|
+ ADD X4, X3, X3
|
|
|
+ VXOR D2, A2, D2
|
|
|
+ VPERM D0, D0, SIXTEEN, D0
|
|
|
+ XOR X0, X15, X15
|
|
|
+ XOR X1, X12, X12
|
|
|
+ VPERM D1, D1, SIXTEEN, D1
|
|
|
+ VPERM D2, D2, SIXTEEN, D2
|
|
|
+ XOR X2, X13, X13
|
|
|
+ XOR X3, X14, X14
|
|
|
+ VADDUWM C0, D0, C0
|
|
|
+ VADDUWM C1, D1, C1
|
|
|
+ ROTLW $16, X15, X15
|
|
|
+ ROTLW $16, X12, X12
|
|
|
+ VADDUWM C2, D2, C2
|
|
|
+ VXOR B0, C0, T0
|
|
|
+ ROTLW $16, X13, X13
|
|
|
+ ROTLW $16, X14, X14
|
|
|
+ VXOR B1, C1, T1
|
|
|
+ VXOR B2, C2, T2
|
|
|
+ ADD X15, X10, X10
|
|
|
+ ADD X12, X11, X11
|
|
|
+ VRLW T0, TWELVE, B0
|
|
|
+ VRLW T1, TWELVE, B1
|
|
|
+ ADD X13, X8, X8
|
|
|
+ ADD X14, X9, X9
|
|
|
+ VRLW T2, TWELVE, B2
|
|
|
+ VADDUWM A0, B0, A0
|
|
|
+ XOR X10, X5, X5
|
|
|
+ XOR X11, X6, X6
|
|
|
+ VADDUWM A1, B1, A1
|
|
|
+ VADDUWM A2, B2, A2
|
|
|
+ XOR X8, X7, X7
|
|
|
+ XOR X9, X4, X4
|
|
|
+ VXOR D0, A0, D0
|
|
|
+ VXOR D1, A1, D1
|
|
|
+ ROTLW $12, X5, X5
|
|
|
+ ROTLW $12, X6, X6
|
|
|
+ VXOR D2, A2, D2
|
|
|
+ VPERM D0, D0, TWENTY4, D0
|
|
|
+ ROTLW $12, X7, X7
|
|
|
+ ROTLW $12, X4, X4
|
|
|
+ VPERM D1, D1, TWENTY4, D1
|
|
|
+ VPERM D2, D2, TWENTY4, D2
|
|
|
+ ADD X5, X0, X0
|
|
|
+ ADD X6, X1, X1
|
|
|
+ VADDUWM C0, D0, C0
|
|
|
+ VADDUWM C1, D1, C1
|
|
|
+ ADD X7, X2, X2
|
|
|
+ ADD X4, X3, X3
|
|
|
+ VADDUWM C2, D2, C2
|
|
|
+ VXOR B0, C0, T0
|
|
|
+ XOR X0, X15, X15
|
|
|
+ XOR X1, X12, X12
|
|
|
+ VXOR B1, C1, T1
|
|
|
+ VXOR B2, C2, T2
|
|
|
+ XOR X2, X13, X13
|
|
|
+ XOR X3, X14, X14
|
|
|
+ VRLW T0, SEVEN, B0
|
|
|
+ VRLW T1, SEVEN, B1
|
|
|
+ ROTLW $8, X15, X15
|
|
|
+ ROTLW $8, X12, X12
|
|
|
+ VRLW T2, SEVEN, B2
|
|
|
+ VSLDOI $8, C0, C0, C0
|
|
|
+ ROTLW $8, X13, X13
|
|
|
+ ROTLW $8, X14, X14
|
|
|
+ VSLDOI $8, C1, C1, C1
|
|
|
+ VSLDOI $8, C2, C2, C2
|
|
|
+ ADD X15, X10, X10
|
|
|
+ ADD X12, X11, X11
|
|
|
+ VSLDOI $4, B0, B0, B0
|
|
|
+ VSLDOI $4, B1, B1, B1
|
|
|
+ ADD X13, X8, X8
|
|
|
+ ADD X14, X9, X9
|
|
|
+ VSLDOI $4, B2, B2, B2
|
|
|
+ VSLDOI $12, D0, D0, D0
|
|
|
+ XOR X10, X5, X5
|
|
|
+ XOR X11, X6, X6
|
|
|
+ VSLDOI $12, D1, D1, D1
|
|
|
+ VSLDOI $12, D2, D2, D2
|
|
|
+ XOR X8, X7, X7
|
|
|
+ XOR X9, X4, X4
|
|
|
+ ROTLW $7, X5, X5
|
|
|
+ ROTLW $7, X6, X6
|
|
|
+ ROTLW $7, X7, X7
|
|
|
+ ROTLW $7, X4, X4
|
|
|
+ BC 0x10, 0, loop_vmx
|
|
|
+
|
|
|
+ SUB $256, LEN, LEN
|
|
|
+
|
|
|
+ // Accumulate key block
|
|
|
+ ADD $0x61707865, X0, X0
|
|
|
+ ADD $0x3320646e, X1, X1
|
|
|
+ ADD $0x79622d32, X2, X2
|
|
|
+ ADD $0x6b206574, X3, X3
|
|
|
+ ADD TMP0, X4, X4
|
|
|
+ ADD TMP1, X5, X5
|
|
|
+ ADD TMP2, X6, X6
|
|
|
+ ADD TMP3, X7, X7
|
|
|
+ MOVWZ 16(KEY), TMP0
|
|
|
+ MOVWZ 20(KEY), TMP1
|
|
|
+ MOVWZ 24(KEY), TMP2
|
|
|
+ MOVWZ 28(KEY), TMP3
|
|
|
+ ADD TMP0, X8, X8
|
|
|
+ ADD TMP1, X9, X9
|
|
|
+ ADD TMP2, X10, X10
|
|
|
+ ADD TMP3, X11, X11
|
|
|
+
|
|
|
+ MOVWZ 12(CNT), TMP0
|
|
|
+ MOVWZ 8(CNT), TMP1
|
|
|
+ MOVWZ 4(CNT), TMP2
|
|
|
+ MOVWZ 0(CNT), TEMP
|
|
|
+ ADD TMP0, X15, X15
|
|
|
+ ADD TMP1, X14, X14
|
|
|
+ ADD TMP2, X13, X13
|
|
|
+ ADD TEMP, X12, X12
|
|
|
+
|
|
|
+ // Accumulate key block
|
|
|
+ VADDUWM A0, K0, A0
|
|
|
+ VADDUWM A1, K0, A1
|
|
|
+ VADDUWM A2, K0, A2
|
|
|
+ VADDUWM B0, K1, B0
|
|
|
+ VADDUWM B1, K1, B1
|
|
|
+ VADDUWM B2, K1, B2
|
|
|
+ VADDUWM C0, K2, C0
|
|
|
+ VADDUWM C1, K2, C1
|
|
|
+ VADDUWM C2, K2, C2
|
|
|
+ VADDUWM D0, K3, D0
|
|
|
+ VADDUWM D1, K4, D1
|
|
|
+ VADDUWM D2, K5, D2
|
|
|
+
|
|
|
+ // Increment counter
|
|
|
+ ADD $4, TEMP, TEMP
|
|
|
+ MOVW TEMP, 0(CNT)
|
|
|
+
|
|
|
+ VADDUWM K3, FOUR, K3
|
|
|
+ VADDUWM K4, FOUR, K4
|
|
|
+ VADDUWM K5, FOUR, K5
|
|
|
+
|
|
|
+ // XOR the input slice (INP) with the keystream, which is stored in GPRs (X0-X3).
|
|
|
+
|
|
|
+ // Load input (aligned or not)
|
|
|
+ MOVWZ 0(INP), TMP0
|
|
|
+ MOVWZ 4(INP), TMP1
|
|
|
+ MOVWZ 8(INP), TMP2
|
|
|
+ MOVWZ 12(INP), TMP3
|
|
|
+
|
|
|
+ // XOR with input
|
|
|
+ XOR TMP0, X0, X0
|
|
|
+ XOR TMP1, X1, X1
|
|
|
+ XOR TMP2, X2, X2
|
|
|
+ XOR TMP3, X3, X3
|
|
|
+ MOVWZ 16(INP), TMP0
|
|
|
+ MOVWZ 20(INP), TMP1
|
|
|
+ MOVWZ 24(INP), TMP2
|
|
|
+ MOVWZ 28(INP), TMP3
|
|
|
+ XOR TMP0, X4, X4
|
|
|
+ XOR TMP1, X5, X5
|
|
|
+ XOR TMP2, X6, X6
|
|
|
+ XOR TMP3, X7, X7
|
|
|
+ MOVWZ 32(INP), TMP0
|
|
|
+ MOVWZ 36(INP), TMP1
|
|
|
+ MOVWZ 40(INP), TMP2
|
|
|
+ MOVWZ 44(INP), TMP3
|
|
|
+ XOR TMP0, X8, X8
|
|
|
+ XOR TMP1, X9, X9
|
|
|
+ XOR TMP2, X10, X10
|
|
|
+ XOR TMP3, X11, X11
|
|
|
+ MOVWZ 48(INP), TMP0
|
|
|
+ MOVWZ 52(INP), TMP1
|
|
|
+ MOVWZ 56(INP), TMP2
|
|
|
+ MOVWZ 60(INP), TMP3
|
|
|
+ XOR TMP0, X12, X12
|
|
|
+ XOR TMP1, X13, X13
|
|
|
+ XOR TMP2, X14, X14
|
|
|
+ XOR TMP3, X15, X15
|
|
|
+
|
|
|
+ // Store output (aligned or not)
|
|
|
+ MOVW X0, 0(OUT)
|
|
|
+ MOVW X1, 4(OUT)
|
|
|
+ MOVW X2, 8(OUT)
|
|
|
+ MOVW X3, 12(OUT)
|
|
|
+
|
|
|
+ ADD $64, INP, INP // INP points to the end of the slice for the alignment code below
|
|
|
+
|
|
|
+ MOVW X4, 16(OUT)
|
|
|
+ MOVD $16, TMP0
|
|
|
+ MOVW X5, 20(OUT)
|
|
|
+ MOVD $32, TMP1
|
|
|
+ MOVW X6, 24(OUT)
|
|
|
+ MOVD $48, TMP2
|
|
|
+ MOVW X7, 28(OUT)
|
|
|
+ MOVD $64, TMP3
|
|
|
+ MOVW X8, 32(OUT)
|
|
|
+ MOVW X9, 36(OUT)
|
|
|
+ MOVW X10, 40(OUT)
|
|
|
+ MOVW X11, 44(OUT)
|
|
|
+ MOVW X12, 48(OUT)
|
|
|
+ MOVW X13, 52(OUT)
|
|
|
+ MOVW X14, 56(OUT)
|
|
|
+ MOVW X15, 60(OUT)
|
|
|
+ ADD $64, OUT, OUT
|
|
|
+
|
|
|
+ // Load input
|
|
|
+ LVX (INP)(R0), DD0
|
|
|
+ LVX (INP)(TMP0), DD1
|
|
|
+ LVX (INP)(TMP1), DD2
|
|
|
+ LVX (INP)(TMP2), DD3
|
|
|
+ LVX (INP)(TMP3), DD4
|
|
|
+ ADD $64, INP, INP
|
|
|
+
|
|
|
+ VPERM DD1, DD0, INPPERM, DD0 // Align input
|
|
|
+ VPERM DD2, DD1, INPPERM, DD1
|
|
|
+ VPERM DD3, DD2, INPPERM, DD2
|
|
|
+ VPERM DD4, DD3, INPPERM, DD3
|
|
|
+ VXOR A0, DD0, A0 // XOR with input
|
|
|
+ VXOR B0, DD1, B0
|
|
|
+ LVX (INP)(TMP0), DD1 // Keep loading input
|
|
|
+ VXOR C0, DD2, C0
|
|
|
+ LVX (INP)(TMP1), DD2
|
|
|
+ VXOR D0, DD3, D0
|
|
|
+ LVX (INP)(TMP2), DD3
|
|
|
+ LVX (INP)(TMP3), DD0
|
|
|
+ ADD $64, INP, INP
|
|
|
+ MOVD $63, TMP3 // 63 is not a typo
|
|
|
+ VPERM A0, A0, OUTPERM, A0
|
|
|
+ VPERM B0, B0, OUTPERM, B0
|
|
|
+ VPERM C0, C0, OUTPERM, C0
|
|
|
+ VPERM D0, D0, OUTPERM, D0
|
|
|
+
|
|
|
+ VPERM DD1, DD4, INPPERM, DD4 // Align input
|
|
|
+ VPERM DD2, DD1, INPPERM, DD1
|
|
|
+ VPERM DD3, DD2, INPPERM, DD2
|
|
|
+ VPERM DD0, DD3, INPPERM, DD3
|
|
|
+ VXOR A1, DD4, A1
|
|
|
+ VXOR B1, DD1, B1
|
|
|
+ LVX (INP)(TMP0), DD1 // Keep loading
|
|
|
+ VXOR C1, DD2, C1
|
|
|
+ LVX (INP)(TMP1), DD2
|
|
|
+ VXOR D1, DD3, D1
|
|
|
+ LVX (INP)(TMP2), DD3
|
|
|
+
|
|
|
+ // Note that the LVX address is always rounded down to the nearest 16-byte
|
|
|
+ // boundary, and that it always points to at most 15 bytes beyond the end of
|
|
|
+ // the slice, so we cannot cross a page boundary.
|
|
|
+ LVX (INP)(TMP3), DD4 // Redundant in aligned case.
|
|
|
+ ADD $64, INP, INP
|
|
|
+ VPERM A1, A1, OUTPERM, A1 // Pre-misalign output
|
|
|
+ VPERM B1, B1, OUTPERM, B1
|
|
|
+ VPERM C1, C1, OUTPERM, C1
|
|
|
+ VPERM D1, D1, OUTPERM, D1
|
|
|
+
|
|
|
+ VPERM DD1, DD0, INPPERM, DD0 // Align Input
|
|
|
+ VPERM DD2, DD1, INPPERM, DD1
|
|
|
+ VPERM DD3, DD2, INPPERM, DD2
|
|
|
+ VPERM DD4, DD3, INPPERM, DD3
|
|
|
+ VXOR A2, DD0, A2
|
|
|
+ VXOR B2, DD1, B2
|
|
|
+ VXOR C2, DD2, C2
|
|
|
+ VXOR D2, DD3, D2
|
|
|
+ VPERM A2, A2, OUTPERM, A2
|
|
|
+ VPERM B2, B2, OUTPERM, B2
|
|
|
+ VPERM C2, C2, OUTPERM, C2
|
|
|
+ VPERM D2, D2, OUTPERM, D2
|
|
|
+
|
|
|
+ ANDCC $15, OUT, X1 // Is out aligned?
|
|
|
+ MOVD OUT, X0
|
|
|
+
|
|
|
+ VSEL A0, B0, OUTMASK, DD0 // Collect pre-misaligned output
|
|
|
+ VSEL B0, C0, OUTMASK, DD1
|
|
|
+ VSEL C0, D0, OUTMASK, DD2
|
|
|
+ VSEL D0, A1, OUTMASK, DD3
|
|
|
+ VSEL A1, B1, OUTMASK, B0
|
|
|
+ VSEL B1, C1, OUTMASK, C0
|
|
|
+ VSEL C1, D1, OUTMASK, D0
|
|
|
+ VSEL D1, A2, OUTMASK, A1
|
|
|
+ VSEL A2, B2, OUTMASK, B1
|
|
|
+ VSEL B2, C2, OUTMASK, C1
|
|
|
+ VSEL C2, D2, OUTMASK, D1
|
|
|
+
|
|
|
+ STVX DD0, (OUT+TMP0)
|
|
|
+ STVX DD1, (OUT+TMP1)
|
|
|
+ STVX DD2, (OUT+TMP2)
|
|
|
+ ADD $64, OUT, OUT
|
|
|
+ STVX DD3, (OUT+R0)
|
|
|
+ STVX B0, (OUT+TMP0)
|
|
|
+ STVX C0, (OUT+TMP1)
|
|
|
+ STVX D0, (OUT+TMP2)
|
|
|
+ ADD $64, OUT, OUT
|
|
|
+ STVX A1, (OUT+R0)
|
|
|
+ STVX B1, (OUT+TMP0)
|
|
|
+ STVX C1, (OUT+TMP1)
|
|
|
+ STVX D1, (OUT+TMP2)
|
|
|
+ ADD $64, OUT, OUT
|
|
|
+
|
|
|
+ BEQ aligned_vmx
|
|
|
+
|
|
|
+ SUB X1, OUT, X2 // in misaligned case edges
|
|
|
+ MOVD $0, X3 // are written byte-by-byte
|
|
|
+
|
|
|
+unaligned_tail_vmx:
|
|
|
+ STVEBX D2, (X2+X3)
|
|
|
+ ADD $1, X3, X3
|
|
|
+ CMPW X3, X1
|
|
|
+ BNE unaligned_tail_vmx
|
|
|
+ SUB X1, X0, X2
|
|
|
+
|
|
|
+unaligned_head_vmx:
|
|
|
+ STVEBX A0, (X2+X1)
|
|
|
+ CMPW X1, $15
|
|
|
+ ADD $1, X1, X1
|
|
|
+ BNE unaligned_head_vmx
|
|
|
+
|
|
|
+ CMPU LEN, $255 // done with 256-byte block yet?
|
|
|
+ BGT loop_outer_vmx
|
|
|
+
|
|
|
+ JMP done_vmx
|
|
|
+
|
|
|
+aligned_vmx:
|
|
|
+ STVX A0, (X0+R0)
|
|
|
+ CMPU LEN, $255 // done with 256-byte block yet?
|
|
|
+ BGT loop_outer_vmx
|
|
|
+
|
|
|
+done_vmx:
|
|
|
+ RET
|