in FourQ_ARM_NEON/ARM/fp2_1271_NEON.c [12:146]
void v2mul1271_a(uint32_t* a, uint32_t* b, uint32_t* c)
{ // Multiplication over GF((2^127-1)^2) using NEON instructions
// Operation: c [r3] = a [r1] * b [r2]
// Representation: 23/23/26/26/26/26/26/26/26/26-bit
asm volatile(
// q0-q2[0] <- A0|A1, q3-q5[0] <- B0|B1
"vld1.8 {d0,d1}, [%0]! \n\t"
"vld1.8 {d2,d3}, [%0]! \n\t"
"vld1.8 {d4}, [%0]! \n\t"
#if defined(INTERLEAVE)
"vshl.i32 q6, q0, #3 \n\t" // q6-q7 = 8*(a0->a8)
"vpush {q4-q7} \n\t"
"vld1.8 {d6,d7}, [%1]! \n\t"
"vshl.i32 d5, d4, #3 \n\t" // q2[1] = 8*(a4|a9)
"vld1.8 {d8,d9}, [%1]! \n\t"
"vshl.i32 q7, q1, #3 \n\t"
"vld1.8 {d10}, [%1]! \n\t"
#else
"vshl.i32 q6, q0, #3 \n\t" // q6-q7 = 8*(a0->a8)
"vld1.8 {d6,d7}, [%1]! \n\t"
"vpush {q4-q7} \n\t"
"vld1.8 {d8,d9}, [%1]! \n\t"
"vld1.8 {d10}, [%1]! \n\t"
"vshl.i32 d5, d4, #3 \n\t" // q2[1] = 8*(a4|a9)
"vshl.i32 q7, q1, #3 \n\t"
#endif
// q11-q15 <- A0*B0|A0*B1, q8-q10 <- A1*B0|A1*B1
"vmull.s32 q8, d6, d0[1] \n\t" // q8 = a5*b0 | a5*b5
"vmlal.s32 q8, d10, d13[1] \n\t" // q8 = a5*b0 + 8*(a6*b4) | a5*b5 + 8*(a6*b9)
"vmlal.s32 q8, d7, d5[1] \n\t" // q8 = a5*b0 + 8*(a6*b4 + a9*b1) | a5*b5 + 8*(a6*b9 + a9*b6)
"vmlal.s32 q8, d9, d14[1] \n\t" // q8 = a5*b0 + 8*(a6*b4 + a9*b1 + a7*b3) | a5*b5 + 8*(a6*b9 + a9*b6 + a7*b8)
"vmlal.s32 q8, d8, d15[1] \n\t" // q8 = a5*b0 + 8*(a6*b4 + a9*b1 + a7*b3 + a8*b2) | a5*b5 + 8*(a6*b9 + a9*b6 + a7*b8 + a8*b7)
"vmull.s32 q9, d7, d0[1] \n\t" // q9 = a5*b1 | a5*b6
"vmlal.s32 q9, d6, d1[1] \n\t" // q9 = a5*b1 + a6*b0 | a5*b6 + a6*b5
"vmlal.s32 q9, d10, d14[1] \n\t" // q9 = a5*b1 + a6*b0 + 8*(a7*b4) | a5*b6 + a6*b5 + 8*(a7*b9)
"vmlal.s32 q9, d8, d5[1] \n\t" // q9 = a5*b1 + a6*b0 + 8*(a7*b4 + a9*b2) | a5*b6 + a6*b5 + 8*(a7*b9 + a9*b7)
"vmlal.s32 q9, d9, d15[1] \n\t" // q9 = a5*b1 + a6*b0 + 8*(a7*b4 + a9*b2 + a8*b3) | a5*b6 + a6*b5 + 8*(a7*b9 + a9*b7 + a8*b8)
"vmull.s32 q10, d8, d0[1] \n\t" // q10 = a5*b2 | a5*b7
"vmlal.s32 q10, d6, d2[1] \n\t" // q10 = a5*b2 + a7*b0 | a5*b7 + a7*b5
"vmlal.s32 q10, d7, d1[1] \n\t" // q10 = a5*b2 + a7*b0 + a6*b1 | a5*b7 + a7*b5 + a6*b6
"vmlal.s32 q10, d10, d15[1] \n\t" // q10 = a5*b2 + a7*b0 + a6*b1 + 8*(a8*b4) | a5*b7 + a7*b5 + a6*b6 + 8*(a8*b9)
"vmlal.s32 q10, d9, d5[1] \n\t" // q10 = a5*b2 + a7*b0 + a6*b1 + 8*(a8*b4 + a9*b3) | a5*b7 + a7*b5 + a6*b6 + 8*(a8*b9 + a9*b8)
"vmull.s32 q11, d6, d0[0] \n\t" // q11 = a0*b0 | a0*b5
"vmlal.s32 q11, d10, d13[0] \n\t" // q11 = a0*b0 + 8*(a1*b4) | a0*b5 + 8*(a1*b9)
"vmlal.s32 q11, d7, d5[0] \n\t" // q11 = a0*b0 + 8*(a1*b4 + a4*b1) | a0*b5 + 8*(a1*b9 + a4*b6)
"vmlal.s32 q11, d9, d14[0] \n\t" // q11 = a0*b0 + 8*(a1*b4 + a4*b1 + a2*b3) | a0*b5 + 8*(a1*b9 + a4*b6 + a2*b8)
"vmlal.s32 q11, d8, d15[0] \n\t" // q11 = a0*b0 + 8*(a1*b4 + a4*b1 + a2*b3 + a3*b2) | a0*b5 + 8*(a1*b9 + a4*b6 + a2*b8 + a3*b7)
"vmull.s32 q12, d7, d0[0] \n\t" // q12 = a0*b1 | a0*b6
"vmlal.s32 q12, d6, d1[0] \n\t" // q12 = a0*b1 + a1*b0 | a0*b6 + a1*b5
"vmlal.s32 q12, d10, d14[0] \n\t" // q12 = a0*b1 + a1*b0 + 8*(a2*b4) | a0*b6 + a1*b5 + 8*(a2*b9)
"vmlal.s32 q12, d8, d5[0] \n\t" // q12 = a0*b1 + a1*b0 + 8*(a2*b4 + a4*b2) | a0*b6 + a1*b5 + 8*(a2*b9 + a4*b7)
"vmlal.s32 q12, d9, d15[0] \n\t" // q12 = a0*b1 + a1*b0 + 8*(a2*b4 + a4*b2 + a3*b3) | a0*b6 + a1*b5 + 8*(a2*b9 + a4*b7 + a3*b8)
"vmull.s32 q13, d8, d0[0] \n\t" // q13 = a0*b2 | a0*b7
"vmlal.s32 q13, d6, d2[0] \n\t" // q13 = a0*b2 + a2*b0 | a0*b7 + a2*b5
"vmlal.s32 q13, d7, d1[0] \n\t" // q13 = a0*b2 + a2*b0 + a1*b1 | a0*b7 + a2*b5 + a1*b6
"vmlal.s32 q13, d10, d15[0] \n\t" // q13 = a0*b2 + a2*b0 + a1*b1 + 8*(a3*b4) | a0*b7 + a2*b5 + a1*b6 + 8*(a3*b9)
"vmlal.s32 q13, d9, d5[0] \n\t" // q13 = a0*b2 + a2*b0 + a1*b1 + 8*(a3*b4 + a4*b3) | a0*b7 + a2*b5 + a1*b6 + 8*(a3*b9 + a4*b8)
"vmull.s32 q14, d9, d0[0] \n\t" // q14 = a0*b3 | a0*b8
"vmlal.s32 q14, d6, d3[0] \n\t" // q14 = a0*b3 + a3*b0 | a0*b8 + a3*b5
"vmlal.s32 q14, d8, d1[0] \n\t" // q14 = a0*b3 + a3*b0 + a1*b2 | a0*b8 + a3*b5 + a1*b7
"vmlal.s32 q14, d7, d2[0] \n\t" // q14 = a0*b3 + a3*b0 + a1*b2 + a2*b1 | a0*b8 + a3*b5 + a1*b7 + a2*b6
"vmlal.s32 q14, d10, d5[0] \n\t" // q14 = a0*b3 + a3*b0 + a1*b2 + a2*b1 + 8*(a4*b4) | a0*b8 + a3*b5 + a1*b7 + a2*b6 + 8*(a4*b9)
"vmull.s32 q15, d10, d0[0] \n\t" // q15 = a0*b4 | a0*b9
"vmlal.s32 q15, d6, d4[0] \n\t" // q15 = a0*b4 + a4*b0 | a0*b9 + a4*b5
"vmlal.s32 q15, d9, d1[0] \n\t" // q15 = a0*b4 + a4*b0 + a1*b3 | a0*b9 + a4*b5 + a1*b8
"vmlal.s32 q15, d7, d3[0] \n\t" // q15 = a0*b4 + a4*b0 + a1*b3 + a3*b1 | a0*b9 + a4*b5 + a1*b8 + a3*b6
"vmlal.s32 q15, d8, d2[0] \n\t" // q15 = a0*b4 + a4*b0 + a1*b3 + a3*b1 + a2*b2 | a0*b9 + a4*b5 + a1*b8 + a3*b6 + a2*b7
// q11[0]->q13[0] = A0*B0 - A1*B1, q11[1]->q13[1] = A0*B0 + A1*B1
"vsub.s64 d22, d22, d17 \n\t"
"vsub.s64 d24, d24, d19 \n\t"
"vsub.s64 d26, d26, d21 \n\t"
"vadd.s64 d23, d23, d16 \n\t"
"vadd.s64 d25, d25, d18 \n\t"
"vadd.s64 d27, d27, d20 \n\t"
"vshr.s64 q10, q11, #26 \n\t" ///
// Complete computation A1*B0|A1*B1, q8-q9 <- A1*B0|A1*B1
"vmull.s32 q8, d9, d0[1] \n\t" // q8 = a5*b3 | a5*b8
"vmlal.s32 q8, d6, d3[1] \n\t" // q8 = a5*b3 + a8*b0 | a5*b8 + a8*b5
"vmlal.s32 q8, d8, d1[1] \n\t" // q8 = a5*b3 + a8*b0 + a6*b2 | a5*b8 + a8*b5 + a6*b7
"vmlal.s32 q8, d7, d2[1] \n\t" // q8 = a5*b3 + a8*b0 + a6*b2 + a7*b1 | a5*b8 + a8*b5 + a6*b7 + a7*b6
"vmlal.s32 q8, d10, d5[1] \n\t" // q8 = a5*b3 + a8*b0 + a6*b2 + a7*b1 + 8*(a9*b4) | a5*b8 + a8*b5 + a6*b7 + a7*b6 + 8*(a9*b9)
"vmull.s32 q9, d10, d0[1] \n\t" // q9 = a5*b4 | a5*b9
"vmlal.s32 q9, d6, d4[1] \n\t" // q9 = a5*b4 + a9*b0 | a5*b9 + a9*b5
"vmlal.s32 q9, d9, d1[1] \n\t" // q9 = a5*b4 + a9*b0 + a6*b3 | a5*b9 + a9*b5 + a6*b8
"vmlal.s32 q9, d7, d3[1] \n\t" // q9 = a5*b4 + a9*b0 + a6*b3 + a8*b1 | a5*b9 + a9*b5 + a6*b8 + a8*b6
"vmlal.s32 q9, d8, d2[1] \n\t" // q9 = a5*b4 + a9*b0 + a6*b3 + a8*b1 + a7*b2 | a5*b9 + a9*b5 + a6*b8 + a8*b6 + a7*b7
"vadd.s64 q10, q12, q10 \n\t" ///
// Complete q14[0]->q15[0] = A0*B0 - A1*B1, q14[1]->q15[0] = A0*B1 + A1*B0
"vmov.i64 q7, 0xFFFFFFFF \n\t" // mask_26
"vadd.s64 d29, d29, d16 \n\t"
"vsub.s64 d28, d28, d17 \n\t"
"vshr.s64 q8, q10, #26 \n\t" ///
"vadd.s64 d31, d31, d18 \n\t"
"vadd.s64 q8, q13, q8 \n\t" ///
"vsub.s64 d30, d30, d19 \n\t"
// Reduction
"vshr.s64 q9, q8, #26 \n\t"
"vshr.u64 q7, q7, #6 \n\t"
"vadd.s64 q9, q14, q9 \n\t"
"vand.u64 q1, q10, q7 \n\t"
"vand.u64 q0, q11, q7 \n\t"
"vshr.s64 q10, q9, #26 \n\t"
"vand.u64 q2, q8, q7 \n\t"
"vadd.s64 q10, q15, q10 \n\t"
"vshr.u64 q6, q7, #3 \n\t" // mask_23
"vand.u64 q3, q9, q7 \n\t"
"vshr.s64 q8, q10, #23 \n\t"
"vand.u64 q11, q10, q6 \n\t"
"vand.u64 q12, q8, q7 \n\t"
"vshr.s64 q6, q8, #26 \n\t"
"vadd.s64 q0, q0, q12 \n\t"
"vadd.s64 q1, q1, q6 \n\t"
"vst2.32 {d0[0],d1[0]}, [%2]! \n\t"
"vst2.32 {d2[0],d3[0]}, [%2]! \n\t"
#if defined(INTERLEAVE)
"vpop {q4-q7} \n\t"
#endif
"vst2.32 {d4[0],d5[0]}, [%2]! \n\t"
"vst2.32 {d6[0],d7[0]}, [%2]! \n\t"
"vst2.32 {d22[0],d23[0]}, [%2]! \n\t"
#if !defined(INTERLEAVE)
"vpop {q4-q7} \n\t"
#endif
:
:"r"(&a[0]), "r"(&b[0]), "r"(&c[0])
);
return;
}