in FourQ_ARM_NEON/ARM/fp2_1271_NEON.c [756:925]
void v2muldblsub1271_a(uint32_t* a, uint32_t* b, uint32_t* c, uint32_t* d, uint32_t* e, uint32_t* f)
{ // Multiplication/addition/subtraction over GF((2^127-1)^2) combining ARM and NEON instructions
// Operation: c = a * b, f = 2*d - e in GF((2^127-1)^2)
// 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"
"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"
// 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)
"push {r6-r9} \n\t"
"ldm %3!, {r6,r7} \n\t" //*****
"ldm %4!, {r8,r9} \n\t" //*****
"add r6, r6 \n\t" //*****
"add r7, r7 \n\t" //*****
"sub r6, r8 \n\t" //*****
"sub r7, r9 \n\t" //*****
"stm %5!, {r6,r7} \n\t" //*****
"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
"ldm %3!, {r6,r7} \n\t" //*****
"ldm %4!, {r8,r9} \n\t" //*****
"add r6, r6 \n\t" //*****
"add r7, r7 \n\t" //*****
"sub r6, r8 \n\t" //*****
"sub r7, r9 \n\t" //*****
"stm %5!, {r6,r7} \n\t" //*****
// 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"
"ldm %3!, {r6,r7} \n\t" //*****
"ldm %4!, {r8,r9} \n\t" //*****
"add r6, r6 \n\t" //*****
"add r7, r7 \n\t" //*****
"sub r6, r8 \n\t" //*****
"sub r7, r9 \n\t" //*****
"stm %5!, {r6,r7} \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
"ldm %3!, {r6,r7} \n\t" //*****
"ldm %4!, {r8,r9} \n\t" //*****
"add r6, r6 \n\t" //*****
"add r7, r7 \n\t" //*****
"sub r6, r8 \n\t" //*****
"sub r7, r9 \n\t" //*****
"stm %5!, {r6,r7} \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.u64 q7, q7, #6 \n\t"
"vadd.s64 d31, d31, d18 \n\t"
"vsub.s64 d30, d30, d19 \n\t"
"ldm %3!, {r6,r7} \n\t" //*****
"ldm %4!, {r8,r9} \n\t" //*****
"add r6, r6 \n\t" //*****
"add r7, r7 \n\t" //*****
"sub r6, r8 \n\t" //*****
"sub r7, r9 \n\t" //*****
"stm %5!, {r6,r7} \n\t" //*****
"pop {r6-r9} \n\t"
// Reduction
"vshr.u64 q6, q7, #3 \n\t" // mask_23
"vshr.s64 q10, q11, #26 \n\t"
"vand.u64 q0, q11, q7 \n\t"
"vshr.s64 q9, q14, #26 \n\t"
"vand.u64 q3, q14, q7 \n\t"
"vadd.s64 q10, q12, q10 \n\t"
"vadd.s64 q9, q15, q9 \n\t"
"vand.u64 q1, q10, q7 \n\t"
"vand.u64 q11, q9, q6 \n\t"
"vshr.s64 q10, q10, #26 \n\t"
"vshr.s64 q9, q9, #23 \n\t"
"vadd.s64 q10, q13, q10 \n\t"
"vand.u64 q12, q9, q7 \n\t"
"vand.u64 q2, q10, q7 \n\t"
"vshr.s64 q10, q10, #26 \n\t"
"vshr.s64 q6, q9, #26 \n\t"
"vadd.s64 q10, q3, q10 \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"
"vshr.s64 q9, q10, #26 \n\t"
"vst2.32 {d2[0],d3[0]}, [%2]! \n\t"
"vand.u64 q3, q10, q7 \n\t"
"vst2.32 {d4[0],d5[0]}, [%2]! \n\t"
"vpop {q4-q7} \n\t"
"vadd.s64 q11, q11, q9 \n\t"
"vst2.32 {d6[0],d7[0]}, [%2]! \n\t"
"vst2.32 {d22[0],d23[0]}, [%2]! \n\t"
:
:"r"(&a[0]), "r"(&b[0]), "r"(&c[0]), "r"(&d[0]), "r"(&e[0]), "r"(&f[0])
:"memory","r6","r7","r8","r9"
);
return;
}