void v2muladdsub1271_a()

in FourQ_ARM_NEON/ARM/fp2_1271_NEON.c [255:429]


void v2muladdsub1271_a(uint32_t* a, uint32_t* b, uint32_t* c, uint32_t* d, uint32_t* e, uint32_t* f, uint32_t* g)  
{ // Multiplication/addition over GF((2^127-1)^2) combining ARM and NEON instructions
  // Operation: c = a * b, f = d + e, g = 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         {r7-r12}                 	\n\t"
    "ldm          %3!, {r7,r8}              \n\t"    //***** 
    "ldm          %4!, {r9,r10}             \n\t"    //***** 
    "add          r11, r7, r9               \n\t"    //***** 
    "add          r12, r8, r10              \n\t"    //***** 
    "sub          r7, r9                    \n\t"    //***** 
    "sub          r8, r10                   \n\t"    //***** 
    "stm          %5!, {r11,r12}            \n\t"    //*****
    "stm          %6!, {r7,r8}              \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!, {r7,r8}              \n\t"    //***** 
    "ldm          %4!, {r9,r10}             \n\t"    //***** 
    "add          r11, r7, r9               \n\t"    //***** 
    "add          r12, r8, r10              \n\t"    //***** 
    "sub          r7, r9                    \n\t"    //***** 
    "sub          r8, r10                   \n\t"    //***** 
    "stm          %5!, {r11,r12}            \n\t"    //*****
    "stm          %6!, {r7,r8}              \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!, {r7,r8}              \n\t"    //***** 
    "ldm          %4!, {r9,r10}             \n\t"    //***** 
    "add          r11, r7, r9               \n\t"    //***** 
    "add          r12, r8, r10              \n\t"    //***** 
    "sub          r7, r9                    \n\t"    //***** 
    "sub          r8, r10                   \n\t"    //***** 
    "stm          %5!, {r11,r12}            \n\t"    //*****
    "stm          %6!, {r7,r8}              \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!, {r7,r8}              \n\t"    //***** 
    "ldm          %4!, {r9,r10}             \n\t"    //***** 
    "add          r11, r7, r9               \n\t"    //***** 
    "add          r12, r8, r10              \n\t"    //***** 
    "sub          r7, r9                    \n\t"    //***** 
    "sub          r8, r10                   \n\t"    //***** 
    "stm          %5!, {r11,r12}            \n\t"    //*****
    "stm          %6!, {r7,r8}              \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!, {r7,r8}              \n\t"    //***** 
    "ldm          %4!, {r9,r10}             \n\t"    //***** 
    "add          r11, r7, r9               \n\t"    //***** 
    "add          r12, r8, r10              \n\t"    //***** 
    "sub          r7, r9                    \n\t"    //***** 
    "sub          r8, r10                   \n\t"    //***** 
    "stm          %5!, {r11,r12}            \n\t"    //*****
    "stm          %6!, {r7,r8}              \n\t"    //*****
    "pop          {r7-r12}                 	\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]), "r"(&g[0])
    :"memory","r7","r8","r9","r10","r11","r12"
	);
	return;
}