void v2mulsub1271_a()

in FourQ_ARM_NEON/ARM/fp2_1271_NEON.c [594:753]


void v2mulsub1271_a(uint32_t* a, uint32_t* b, uint32_t* c, uint32_t* d, uint32_t* e, uint32_t* f)  
{ // Multiplication/subtraction over GF((2^127-1)^2) combining ARM and NEON instructions 
  // Operation: c = a * b, f = 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"    //***** 
    "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"    //***** 
    "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"    //***** 
    "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"    //***** 
    "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"    //***** 
    "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;
}