diff --git a/sm9/bn256/gfp_ppc64x.go b/sm9/bn256/gfp_ppc64x.go index b6e2636..fb37276 100644 --- a/sm9/bn256/gfp_ppc64x.go +++ b/sm9/bn256/gfp_ppc64x.go @@ -31,3 +31,8 @@ func gfpTripleAsm(c, a *gfP) // //go:noescape func gfpSubAsm(c, a, b *gfP) + +// Montgomery multiplication. Sets res = in1 * in2 * R⁻¹ mod p. +// +//go:noescape +func gfpMulAsm(c, a, b *gfP) diff --git a/sm9/bn256/gfp_ppc64x.s b/sm9/bn256/gfp_ppc64x.s index d64c828..405cb46 100644 --- a/sm9/bn256/gfp_ppc64x.s +++ b/sm9/bn256/gfp_ppc64x.s @@ -201,3 +201,536 @@ TEXT ·gfpTripleAsm(SB),0,$0-16 STXVD2X T0, (R0+R3) STXVD2X T1, (R6+R3) RET + +#undef X1L +#undef X1H +#undef Y1L +#undef Y1H +#undef T1L +#undef T1H +#undef T0 +#undef T1 +#undef T2 +#undef SEL1 +#undef ZERO +#undef CAR1 +#undef CAR2 +#undef TT0 +#undef TT1 +#undef PL +#undef PH + +// Vector multiply word +// +// VMLF x0, x1, out_low +// VMLHF x0, x1, out_hi +#define VMULT(x1, x2, out_low, out_hi) \ + VMULEUW x1, x2, TMP1; \ + VMULOUW x1, x2, TMP2; \ + VMRGEW TMP1, TMP2, out_hi; \ + VMRGOW TMP1, TMP2, out_low + +// +// Vector multiply add word +// +// VMALF x0, x1, y, out_low +// VMALHF x0, x1, y, out_hi +#define VMULT_ADD(x1, x2, y, one, out_low, out_hi) \ + VMULEUW y, one, TMP1; \ + VMULOUW y, one, TMP2; \ + VMULEUW x1, x2, out_hi; \ + VMULOUW x1, x2, out_low; \ + VADDUDM TMP1, out_hi, TMP1; \ + VADDUDM TMP2, out_low, TMP2; \ + VMRGEW TMP1, TMP2, out_hi; \ + VMRGOW TMP1, TMP2, out_low + + +// --------------------------------------- +// gfpMulInternal +#define X0 V0 +#define X1 V1 +#define Y0 V2 +#define Y1 V3 +#define M1 V4 +#define M0 V5 +#define T0 V6 +#define T1 V7 +#define T2 V8 +#define YDIG V9 + +#define ADD1 V16 +#define ADD1H V17 +#define ADD2 V18 +#define ADD2H V19 +#define RED1 V20 +#define RED1H V21 +#define RED2 V22 +#define RED2H V23 +#define CAR1 V24 +#define CAR1M V25 + +#define MK0 V30 +#define K0 V31 + +// TMP1, TMP2 used in +// VMULT macros +#define TMP1 V13 +#define TMP2 V27 +#define ONE V29 // 1s splatted by word + +TEXT gfpMulInternal<>(SB), NOSPLIT, $0 + // ---------------------------------------------------------------------------/ + // VREPF $3, Y0, YDIG + VSPLTW $3, Y0, YDIG + VSPLTISW $1, ONE + + // VMLF X0, YDIG, ADD1 + // VMLF X1, YDIG, ADD2 + // VMLHF X0, YDIG, ADD1H + // VMLHF X1, YDIG, ADD2H + VMULT(X0, YDIG, ADD1, ADD1H) + VMULT(X1, YDIG, ADD2, ADD2H) + + // VMLF ADD1, K0, MK0 + // VREPF $3, MK0, MK0 + VMULUWM ADD1, K0, MK0 + VSPLTW $3, MK0, MK0 + + // VMALF M0, MK0, ADD1, RED1 + // VMALHF M0, MK0, ADD1, RED1H + // VMALF M1, MK0, ADD2, RED2 + // VMALHF M1, MK0, ADD2, RED2H + VMULT_ADD(M0, MK0, ADD1, ONE, RED1, RED1H) + VMULT_ADD(M1, MK0, ADD2, ONE, RED2, RED2H) + + VSPLTISB $0, T2 // VZERO T2 + + VSLDOI $12, RED2, RED1, RED1 // VSLDB + VSLDOI $12, T2, RED2, RED2 // VSLDB + + VADDCUQ RED1, ADD1H, CAR1 // VACCQ + VADDUQM RED1, ADD1H, T0 // VAQ + VADDCUQ RED1H, T0, CAR1M // VACCQ + VADDUQM RED1H, T0, T0 // VAQ + + // << ready for next MK0 + + VADDEUQM RED2, ADD2H, CAR1, T1 // VACQ + VADDECUQ RED2, ADD2H, CAR1, CAR1 // VACCCQ + VADDECUQ RED2H, T1, CAR1M, T2 // VACCCQ + VADDEUQM RED2H, T1, CAR1M, T1 // VACQ + VADDUQM CAR1, T2, T2 // VAQ + + // --------------------------------------------------- +/* * + * ---+--------+--------+ + * T2| T1 | T0 | + * ---+--------+--------+ + * *(add)* + * +--------+--------+ + * | X1 | X0 | + * +--------+--------+ + * *(mul)* + * +--------+--------+ + * | YDIG | YDIG | + * +--------+--------+ + * *(add)* + * +--------+--------+ + * | M1 | M0 | + * +--------+--------+ + * *(mul)* + * +--------+--------+ + * | MK0 | MK0 | + * +--------+--------+ + * + * --------------------- + * + * +--------+--------+ + * | ADD2 | ADD1 | + * +--------+--------+ + * +--------+--------+ + * | ADD2H | ADD1H | + * +--------+--------+ + * +--------+--------+ + * | RED2 | RED1 | + * +--------+--------+ + * +--------+--------+ + * | RED2H | RED1H | + * +--------+--------+ + */ + // VREPF $2, Y0, YDIG + VSPLTW $2, Y0, YDIG + + // VMALF X0, YDIG, T0, ADD1 + // VMALF X1, YDIG, T1, ADD2 + // VMALHF X0, YDIG, T0, ADD1H + // VMALHF X1, YDIG, T1, ADD2H + VMULT_ADD(X0, YDIG, T0, ONE, ADD1, ADD1H) + VMULT_ADD(X1, YDIG, T1, ONE, ADD2, ADD2H) + + // VMLF ADD1, K0, MK0 + // VREPF $3, MK0, MK0 + VMULUWM ADD1, K0, MK0 + VSPLTW $3, MK0, MK0 + + // VMALF M0, MK0, ADD1, RED1 + // VMALHF M0, MK0, ADD1, RED1H + // VMALF M1, MK0, ADD2, RED2 + // VMALHF M1, MK0, ADD2, RED2H + VMULT_ADD(M0, MK0, ADD1, ONE, RED1, RED1H) + VMULT_ADD(M1, MK0, ADD2, ONE, RED2, RED2H) + + VSLDOI $12, RED2, RED1, RED1 // VSLDB + VSLDOI $12, T2, RED2, RED2 // VSLDB + + VADDCUQ RED1, ADD1H, CAR1 // VACCQ + VADDUQM RED1, ADD1H, T0 // VAQ + VADDCUQ RED1H, T0, CAR1M // VACCQ + VADDUQM RED1H, T0, T0 // VAQ + + // << ready for next MK0 + + VADDEUQM RED2, ADD2H, CAR1, T1 // VACQ + VADDECUQ RED2, ADD2H, CAR1, CAR1 // VACCCQ + VADDECUQ RED2H, T1, CAR1M, T2 // VACCCQ + VADDEUQM RED2H, T1, CAR1M, T1 // VACQ + VADDUQM CAR1, T2, T2 // VAQ + + // --------------------------------------------------- + // VREPF $1, Y0, YDIG + VSPLTW $1, Y0, YDIG + + // VMALF X0, YDIG, T0, ADD1 + // VMALF X1, YDIG, T1, ADD2 + // VMALHF X0, YDIG, T0, ADD1H + // VMALHF X1, YDIG, T1, ADD2H + VMULT_ADD(X0, YDIG, T0, ONE, ADD1, ADD1H) + VMULT_ADD(X1, YDIG, T1, ONE, ADD2, ADD2H) + + // VMLF ADD1, K0, MK0 + // VREPF $3, MK0, MK0 + VMULUWM ADD1, K0, MK0 + VSPLTW $3, MK0, MK0 + + // VMALF M0, MK0, ADD1, RED1 + // VMALHF M0, MK0, ADD1, RED1H + // VMALF M1, MK0, ADD2, RED2 + // VMALHF M1, MK0, ADD2, RED2H + VMULT_ADD(M0, MK0, ADD1, ONE, RED1, RED1H) + VMULT_ADD(M1, MK0, ADD2, ONE, RED2, RED2H) + + VSLDOI $12, RED2, RED1, RED1 // VSLDB + VSLDOI $12, T2, RED2, RED2 // VSLDB + + VADDCUQ RED1, ADD1H, CAR1 // VACCQ + VADDUQM RED1, ADD1H, T0 // VAQ + VADDCUQ RED1H, T0, CAR1M // VACCQ + VADDUQM RED1H, T0, T0 // VAQ + + // << ready for next MK0 + + VADDEUQM RED2, ADD2H, CAR1, T1 // VACQ + VADDECUQ RED2, ADD2H, CAR1, CAR1 // VACCCQ + VADDECUQ RED2H, T1, CAR1M, T2 // VACCCQ + VADDEUQM RED2H, T1, CAR1M, T1 // VACQ + VADDUQM CAR1, T2, T2 // VAQ + + // --------------------------------------------------- + // VREPF $0, Y0, YDIG + VSPLTW $0, Y0, YDIG + + // VMALF X0, YDIG, T0, ADD1 + // VMALF X1, YDIG, T1, ADD2 + // VMALHF X0, YDIG, T0, ADD1H + // VMALHF X1, YDIG, T1, ADD2H + VMULT_ADD(X0, YDIG, T0, ONE, ADD1, ADD1H) + VMULT_ADD(X1, YDIG, T1, ONE, ADD2, ADD2H) + + // VMLF ADD1, K0, MK0 + // VREPF $3, MK0, MK0 + VMULUWM ADD1, K0, MK0 + VSPLTW $3, MK0, MK0 + + // VMALF M0, MK0, ADD1, RED1 + // VMALHF M0, MK0, ADD1, RED1H + // VMALF M1, MK0, ADD2, RED2 + // VMALHF M1, MK0, ADD2, RED2H + VMULT_ADD(M0, MK0, ADD1, ONE, RED1, RED1H) + VMULT_ADD(M1, MK0, ADD2, ONE, RED2, RED2H) + + VSLDOI $12, RED2, RED1, RED1 + VSLDOI $12, T2, RED2, RED2 + + VADDCUQ RED1, ADD1H, CAR1 // VACCQ + VADDUQM RED1, ADD1H, T0 // VAQ + VADDCUQ RED1H, T0, CAR1M // VACCQ + VADDUQM RED1H, T0, T0 // VAQ + + // << ready for next MK0 + + VADDEUQM RED2, ADD2H, CAR1, T1 // VACQ + VADDECUQ RED2, ADD2H, CAR1, CAR1 // VACCCQ + VADDECUQ RED2H, T1, CAR1M, T2 // VACCCQ + VADDEUQM RED2H, T1, CAR1M, T1 // VACQ + VADDUQM CAR1, T2, T2 // VAQ + + // --------------------------------------------------- + // VREPF $3, Y1, YDIG + VSPLTW $3, Y1, YDIG + + // VMALF X0, YDIG, T0, ADD1 + // VMALF X1, YDIG, T1, ADD2 + // VMALHF X0, YDIG, T0, ADD1H + // VMALHF X1, YDIG, T1, ADD2H + VMULT_ADD(X0, YDIG, T0, ONE, ADD1, ADD1H) + VMULT_ADD(X1, YDIG, T1, ONE, ADD2, ADD2H) + + // VMLF ADD1, K0, MK0 + // VREPF $3, MK0, MK0 + VMULUWM ADD1, K0, MK0 + VSPLTW $3, MK0, MK0 + + // VMALF M0, MK0, ADD1, RED1 + // VMALHF M0, MK0, ADD1, RED1H + // VMALF M1, MK0, ADD2, RED2 + // VMALHF M1, MK0, ADD2, RED2H + VMULT_ADD(M0, MK0, ADD1, ONE, RED1, RED1H) + VMULT_ADD(M1, MK0, ADD2, ONE, RED2, RED2H) + + VSLDOI $12, RED2, RED1, RED1 + VSLDOI $12, T2, RED2, RED2 + + VADDCUQ RED1, ADD1H, CAR1 // VACCQ + VADDUQM RED1, ADD1H, T0 // VAQ + VADDCUQ RED1H, T0, CAR1M // VACCQ + VADDUQM RED1H, T0, T0 // VAQ + + // << ready for next MK0 + + VADDEUQM RED2, ADD2H, CAR1, T1 // VACQ + VADDECUQ RED2, ADD2H, CAR1, CAR1 // VACCCQ + VADDECUQ RED2H, T1, CAR1M, T2 // VACCCQ + VADDEUQM RED2H, T1, CAR1M, T1 // VACQ + VADDUQM CAR1, T2, T2 // VAQ + + // --------------------------------------------------- + // VREPF $2, Y1, YDIG + VSPLTW $2, Y1, YDIG + + // VMALF X0, YDIG, T0, ADD1 + // VMALF X1, YDIG, T1, ADD2 + // VMALHF X0, YDIG, T0, ADD1H + // VMALHF X1, YDIG, T1, ADD2H + VMULT_ADD(X0, YDIG, T0, ONE, ADD1, ADD1H) + VMULT_ADD(X1, YDIG, T1, ONE, ADD2, ADD2H) + + // VMLF ADD1, K0, MK0 + // VREPF $3, MK0, MK0 + VMULUWM ADD1, K0, MK0 + VSPLTW $3, MK0, MK0 + + // VMALF M0, MK0, ADD1, RED1 + // VMALHF M0, MK0, ADD1, RED1H + // VMALF M1, MK0, ADD2, RED2 + // VMALHF M1, MK0, ADD2, RED2H + VMULT_ADD(M0, MK0, ADD1, ONE, RED1, RED1H) + VMULT_ADD(M1, MK0, ADD2, ONE, RED2, RED2H) + + VSLDOI $12, RED2, RED1, RED1 + VSLDOI $12, T2, RED2, RED2 + + VADDCUQ RED1, ADD1H, CAR1 // VACCQ + VADDUQM RED1, ADD1H, T0 // VAQ + VADDCUQ RED1H, T0, CAR1M // VACCQ + VADDUQM RED1H, T0, T0 // VAQ + + // << ready for next MK0 + + VADDEUQM RED2, ADD2H, CAR1, T1 // VACQ + VADDECUQ RED2, ADD2H, CAR1, CAR1 // VACCCQ + VADDECUQ RED2H, T1, CAR1M, T2 // VACCCQ + VADDEUQM RED2H, T1, CAR1M, T1 // VACQ + VADDUQM CAR1, T2, T2 // VAQ + + // --------------------------------------------------- + // VREPF $1, Y1, YDIG + VSPLTW $1, Y1, YDIG + + // VMALF X0, YDIG, T0, ADD1 + // VMALF X1, YDIG, T1, ADD2 + // VMALHF X0, YDIG, T0, ADD1H + // VMALHF X1, YDIG, T1, ADD2H + VMULT_ADD(X0, YDIG, T0, ONE, ADD1, ADD1H) + VMULT_ADD(X1, YDIG, T1, ONE, ADD2, ADD2H) + + // VMLF ADD1, K0, MK0 + // VREPF $3, MK0, MK0 + VMULUWM ADD1, K0, MK0 + VSPLTW $3, MK0, MK0 + + // VMALF M0, MK0, ADD1, RED1 + // VMALHF M0, MK0, ADD1, RED1H + // VMALF M1, MK0, ADD2, RED2 + // VMALHF M1, MK0, ADD2, RED2H + VMULT_ADD(M0, MK0, ADD1, ONE, RED1, RED1H) + VMULT_ADD(M1, MK0, ADD2, ONE, RED2, RED2H) + + VSLDOI $12, RED2, RED1, RED1 + VSLDOI $12, T2, RED2, RED2 + + VADDCUQ RED1, ADD1H, CAR1 // VACCQ + VADDUQM RED1, ADD1H, T0 // VAQ + VADDCUQ RED1H, T0, CAR1M // VACCQ + VADDUQM RED1H, T0, T0 // VAQ + + // << ready for next MK0 + + VADDEUQM RED2, ADD2H, CAR1, T1 // VACQ + VADDECUQ RED2, ADD2H, CAR1, CAR1 // VACCCQ + VADDECUQ RED2H, T1, CAR1M, T2 // VACCCQ + VADDEUQM RED2H, T1, CAR1M, T1 // VACQ + VADDUQM CAR1, T2, T2 // VAQ + + // --------------------------------------------------- + // VREPF $0, Y1, YDIG + VSPLTW $0, Y1, YDIG + + // VMALF X0, YDIG, T0, ADD1 + // VMALF X1, YDIG, T1, ADD2 + // VMALHF X0, YDIG, T0, ADD1H + // VMALHF X1, YDIG, T1, ADD2H + VMULT_ADD(X0, YDIG, T0, ONE, ADD1, ADD1H) + VMULT_ADD(X1, YDIG, T1, ONE, ADD2, ADD2H) + + // VMLF ADD1, K0, MK0 + // VREPF $3, MK0, MK0 + VMULUWM ADD1, K0, MK0 + VSPLTW $3, MK0, MK0 + + // VMALF M0, MK0, ADD1, RED1 + // VMALHF M0, MK0, ADD1, RED1H + // VMALF M1, MK0, ADD2, RED2 + // VMALHF M1, MK0, ADD2, RED2H + VMULT_ADD(M0, MK0, ADD1, ONE, RED1, RED1H) + VMULT_ADD(M1, MK0, ADD2, ONE, RED2, RED2H) + + VSLDOI $12, RED2, RED1, RED1 + VSLDOI $12, T2, RED2, RED2 + + VADDCUQ RED1, ADD1H, CAR1 // VACCQ + VADDUQM RED1, ADD1H, T0 // VAQ + VADDCUQ RED1H, T0, CAR1M // VACCQ + VADDUQM RED1H, T0, T0 // VAQ + + // << ready for next MK0 + + VADDEUQM RED2, ADD2H, CAR1, T1 // VACQ + VADDECUQ RED2, ADD2H, CAR1, CAR1 // VACCCQ + VADDECUQ RED2H, T1, CAR1M, T2 // VACCCQ + VADDEUQM RED2H, T1, CAR1M, T1 // VACQ + VADDUQM CAR1, T2, T2 // VAQ + + // --------------------------------------------------- + + // VZERO RED1 + // VSCBIQ M0, T0, CAR1 + // VSQ M0, T0, ADD1 + // VSBCBIQ T1, M1, CAR1, CAR1M + // VSBIQ T1, M1, CAR1, ADD2 + // VSBIQ T2, RED1, CAR1M, T2 + VSPLTISB $0, RED1 // VZERO RED1 + VSUBCUQ T0, M0, CAR1 // VSCBIQ + VSUBUQM T0, M0, ADD1 // VSQ + VSUBECUQ T1, M1, CAR1, CAR1M // VSBCBIQ + VSUBEUQM T1, M1, CAR1, ADD2 // VSBIQ + VSUBEUQM T2, RED1, CAR1M, T2 // VSBIQ + + // what output to use, ADD2||ADD1 or T1||T0? + VSEL ADD1, T0, T2, T0 + VSEL ADD2, T1, T2, T1 + RET + +#undef X0 +#undef X1 +#undef Y0 +#undef Y1 +#undef M0 +#undef M1 +#undef T0 +#undef T1 +#undef T2 +#undef YDIG + +#undef ADD1 +#undef ADD1H +#undef ADD2 +#undef ADD2H +#undef RED1 +#undef RED1H +#undef RED2 +#undef RED2H +#undef CAR1 +#undef CAR1M + +#undef MK0 +#undef K0 +#undef TMP1 +#undef TMP2 +#undef ONE + +// func gfpMul(c, a, b *gfP) +#define res_ptr R3 +#define x_ptr R4 +#define y_ptr R5 +#define CPOOL R7 +#define N R8 + +#define X0 V0 +#define X1 V1 +#define Y0 V2 +#define Y1 V3 +#define M0 V5 +#define M1 V4 +#define T0 V6 +#define T1 V7 +#define K0 V31 + +TEXT ·gfpMulAsm(SB),NOSPLIT,$0 + MOVD c+0(FP), res_ptr + MOVD a+8(FP), x_ptr + MOVD b+16(FP), y_ptr + + MOVD $16, R16 + + LXVD2X (R0)(x_ptr), X0 + LXVD2X (R16)(x_ptr), X1 + + XXPERMDI X0, X0, $2, X0 + XXPERMDI X1, X1, $2, X1 + + LXVD2X (R0)(y_ptr), Y0 + LXVD2X (R16)(y_ptr), Y1 + + XXPERMDI Y0, Y0, $2, Y0 + XXPERMDI Y1, Y1, $2, Y1 + + MOVD $·p2+0(SB), CPOOL + LXVD2X (CPOOL)(R0), M0 + LXVD2X (CPOOL)(R16), M1 + + XXPERMDI M0, M0, $2, M0 + XXPERMDI M1, M1, $2, M1 + + MOVD $·np+0(SB), CPOOL + LXVD2X (CPOOL)(R0), K0 + VSPLTW $1, K0, K0 + + CALL gfpMulInternal<>(SB) + + XXPERMDI T0, T0, $2, T0 + XXPERMDI T1, T1, $2, T1 + STXVD2X T0, (R0)(res_ptr) + STXVD2X T1, (R16)(res_ptr) + + RET diff --git a/sm9/bn256/gfp_ppc64x_test.go b/sm9/bn256/gfp_ppc64x_test.go index 3bf69e5..1390722 100644 --- a/sm9/bn256/gfp_ppc64x_test.go +++ b/sm9/bn256/gfp_ppc64x_test.go @@ -31,7 +31,7 @@ func TestGfpAsmBasicOperations(t *testing.T) { expectedDouble := fromBigInt(bigFromHex("551de7a0ee24723edcf314ff72f478fac1c7c4e7044238acc3913cfbcdaf7d05")) expectedSub := fromBigInt(bigFromHex("67b381821c52a5624f3304a8149be8461e3bc07adcb872c38aa65051ba53ba97")) expectedNeg := fromBigInt(bigFromHex("7f1d8aad70909be90358f1d02240062433cc3a0248ded72febb879ec33ce6f22")) - //expectedMul := fromBigInt(bigFromHex("3d08bbad376584e4f74bd31f78f716372b96ba8c3f939c12b8d54e79b6489e76")) + expectedMul := fromBigInt(bigFromHex("3d08bbad376584e4f74bd31f78f716372b96ba8c3f939c12b8d54e79b6489e76")) //expectedMul2 := fromBigInt(bigFromHex("1df94a9e05a559ff38e0ab50cece734dc058d33738ceacaa15986a67cbff1ef6")) t.Parallel() @@ -103,20 +103,20 @@ func TestGfpAsmBasicOperations(t *testing.T) { t.Errorf("neg not same when neg self") } }) -/* + t.Run("mul", func(t *testing.T) { ret := &gfP{} - gfpMul(ret, x, y) + gfpMulAsm(ret, x, y) if *expectedMul != *ret { t.Errorf("mul not same") } ret.Set(x) - gfpMul(ret, ret, y) + gfpMulAsm(ret, ret, y) if *expectedMul != *ret { t.Errorf("mul not same when mul self") } }) - +/* t.Run("square", func(t *testing.T) { ret, ret1, ret2 := &gfP{}, &gfP{}, &gfP{} gfpMul(ret, x, y) @@ -137,4 +137,3 @@ func TestGfpAsmBasicOperations(t *testing.T) { }) */ } -