: +r(RgbBuffer), // %0 output readwrite
+r(SrcYUV), // %1
+r(u), // %2
+r(v), // %3
+r(h)
// %4
: r(w) // %5 readonly
add r4, %5, %5 , lsl #1 // r4 = 3*w
mov r8, %5, lsr #3 // r8 = w/8
mov r6, %4, lsr #1 // r6 = h/2
add %4, %1, %5 // %4 = y + w (a row for yuv)
mov r5, %0 // r5 = rgb row's head addr
add %0, r5, r4 // %0 = rgb + 3*w (a row for rgb) next row's head addr
mov r9, #16 //
vdup.8 d8, r9 // d8 = 16
mov r10, #128 //
vdup.8 d9, r10 // d9 = 128
mov r9, #75 //
vdup.16 q5, r9 // q5 = 75
mov r10, #102 //
vdup.16 q6, r10 // q6 = 102
mov r9, #25 //
vdup.16 q7, r9 // q7 = 25
mov r10, #52 //
vdup.16 q8, r10 // q8 = 52
mov r9, #129 //
vdup.16 q9, r9 // q9 = 129
2:
1:
subs r8, r8, #1 // r8 = r8 -1 (for i= w/8; i--;i>0) //======>>> 16 * w/8 * h/2 = w*h (Y)
// load 16 Y
vld1.u8 d0, [%1]! // load 8 Y to d0 ,update %1
vld1.u8 d2, [%4]! // load 8 Y to d2 from the next row
vld1.32 {d4[0]}, [%2]! // load 4 U to d4[0](32bits)
vld1.32 {d4[1]}, [%3]! // load 4 V to d4[1](32bits)
vsubl.u8 q0, d0, d8 // q0 = d0 - d8 = Y1 - 16
vsubl.u8 q1, d2, d8 // q1 = d2 - d8 = Y2 - 16
vsubl.u8 q2, d4, d9 // q2 = d4 - d9 = {U -128,V - 128}
vmov q3, q2 // q3 = q2
vzip.s16 q2, q3 // interleaves
vmul.s16 q10, q3, q8 // q10 = q3*q8 = 52V
vmla.s16 q10, q2, q7 // q10 = q10+q2*q7 = 52(V-128) + 25(U-128)
vmul.s16 q11, q2, q9 // q11 = 25*q2 = 25(U-128)
vmul.s16 q12, q3, q6 // q12 = 102*q3 = 102(V-128)
vmul.s16 q0, q0, q5 // q0 = 75*q0 = 75(Y1-16)
vmul.s16 q1, q1, q5 // q1 = 75*q1 = 75(Y2-16)
vqsub.s16 q13, q0, q10 // q13 = q0 - q10 = 75(Y1-16) - 52(V-128) - 25(U-128)
vqsub.s16 q14, q1, q10 // q14 = q1 - q11 = 75(Y2-16) - 25(U-128)
vqrshrun.s16 d27, q13, #6 // right shift q13's every 4 int 6bits(/64),store the result into d27's 4 shorts
vqrshrun.s16 d30, q14, #6 // right shift q14's every 4 int 6bits(/64),store the result into d30's 4 shorts
vqadd.s16 q10, q0, q11 // q10 = q0 + q11 = 75(Y1-16) + 25(U-128)
vqadd.s16 q11, q1, q11 // q11 = q1 + q11 = 75(Y2-16) + 25(U-128)
vqrshrun.s16 d26, q10, #6 // right shift q10's every 4 int 6bits(/64),store the result into d26's 4 shorts
vqrshrun.s16 d29, q11, #6 // right shift q11's every 4 int 6bits(/64),store the result into d29's 4 shorts
vqadd.s16 q11, q0, q12 // q11 = q0 + q12 = 75(Y1-16) + 102(V-128)
vqadd.s16 q12, q1, q12 // q12 = q1 + q12 = 75(Y2-16) + 102(V-128)
vqrshrun.s16 d28, q11, #6 // right shift q11's every 4 int 6bits(/64),store the result into d28's 4 shorts
vqrshrun.s16 d31, q12, #6 // right shift q12's every 4 int 6bits(/64),store the result into d31's 4 shorts
vst3.8 {d26, d27, d28}, [%0]! // store 8 pixels into rgb's next row's addr
vst3.8 {d29, d30, d31}, [r5]! // store 8 pixels into rgb's head addr
bgt 1b
// state >0 jump to 1:
subs r6, r6, #1 // r6--; for(i=h/2;i--;i>0)
mov r5,%0
// now the head addr will change to the next row's tail ,that is %0(after updated)
add %0,r5,r4
// now the next row head addr will change to (the new head addr + row),that is (r5 + 3w)
add %1, %1, %5 // update the srcYUV into (srcYUV+w)
add %4, %4, %5 // update the next row 's srcYUV into (srcYUV+w)
mov r8, %5, lsr #3 // r8 = w /8
bgt 2b
//
: +r(RgbBuffer), // %0 output readwrite
+r(SrcYUV), // %1
+r(u), // %2
+r(v), // %3
+r(h) // %4
: r(w) // %5 readonly