void v2mul1271_a()

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;
}