fix bugs in div
authoryang <yang.zhang@arm.com>
Thu, 19 Jul 2012 06:25:27 +0000 (14:25 +0800)
committeryang <yang.zhang@arm.com>
Thu, 19 Jul 2012 06:25:27 +0000 (14:25 +0800)
source/NE10_add.neon.s
source/NE10_div.neon.s

index 3cb43749372b6119220fc4a3eb8bfc0978b413c9..19d09e638b0390677b42053e4d8832602969eade 100644 (file)
@@ -146,7 +146,7 @@ add_vec2f_neon:
 .L_check_mainloop_vec2:
         cbz               r3, .L_return_vec2
 
-        @ load the 1st set of values
+        @ load the current set of values
         vld2.32         {q0-q1}, [r1]!
         vld2.32         {q2-q3}, [r2]!
 
index 039f349f0f1a8956686bbcbeb4876ad82892be86..7db7bcccca5e30186da9c1c61ed0fa0766b12a2d 100644 (file)
@@ -26,7 +26,7 @@
 
 
 
-        .balign   4
+        .align   4
         .global   div_float_neon
         .thumb
         .thumb_func
@@ -45,91 +45,60 @@ div_float_neon:
         @  r3: int count & the number of items in the input array that can be
         @                   processed in chunks of 4 vectors
         @
-        @  r4:  the number of items that are left to be processed at the end of
+        @  r4:  the number of items that are residual that will be processed at the begin of
         @                   the input array
         @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
         push              {r4}
-        and               r4, r3, #3          @ r4 = count % 4;
-        sub               r3, r3, r4          @ count = count - r4; This is what's left to be processed after this loop
+        and               r4, r3, #3          @ r4 = count % 4; calculate the residual loop
+        asr               r3, r3, #2          @ r3 = count >> 2; calculate the main loop
 
-        cbz               r3, .L_check_float
+        cbz               r4, .L_check_mainloop_float
 
-        @ load the 1st set of values
-          vld1.32         {q0}, [r1]!
-          vld1.32         {q1}, [r2]!
-          subs            r3, r3, #8          @ 4 for this set, and 4 for the 2nd set
-
-        @ calculate values for the 1st set
-          vrecpe.f32 q3, q1
-          vrecps.f32 q1, q3, q1
-          vmul.f32   q3, q1, q3
-          vmul.f32   q3, q0, q3
-
-
-        @ load the 2nd set of values
-          vld1.32         {q0}, [r1]!
-          vld1.32         {q1}, [r2]!
-
-          ble             .L_mainloopend_float
-
-.L_mainloop_float:
-        @ store the result for the 1st/next (e.g. 3rd) set
-          vst1.32         {d6,d7}, [r0]!
-
-        @ calculate values for the 2nd/next (e.g. 3rd) set
-          vrecpe.f32 q3, q1
-          vrecps.f32 q1, q3, q1
-          vmul.f32   q3, q1, q3
-          vmul.f32   q3, q0, q3
-
-       @ load the next (e.g. 3rd) set of values
-          vld1.32         {q0}, [r1]!
-          vld1.32         {q1}, [r2]!
-          subs            r3, r3, #4
-
-        bgt             .L_mainloop_float             @ loop if r2 is > r3, if we have at least another 4 floats
+.L_residualloop_float:
+        @ process the residual items in the input array
+        vld1.f32          d0[0], [r1]!           @ Fill in d0[0]
+        vld1.f32          d1[0], [r2]!           @ Fill in d1[1]
 
-.L_mainloopend_float:
-        @ the last iteration for this call
-        @ store the result for the set of values before the last one (e.g 2nd set)
-          vst1.32         {d6,d7}, [r0]!
 
-        @ calculate values for the last (e.g. 3rd) set
-          vrecpe.f32 q3, q1
-          vrecps.f32 q1, q3, q1
-          vmul.f32   q3, q1, q3
-          vmul.f32   q3, q0, q3
+        subs              r4, r4, #1
 
-        @ store the result for the last (e.g. 3rd) set
-          vst1.32         {d6,d7}, [r0]!
+        @ values d0 = d0 / d1
+        vrecpe.f32 d3, d1
+        vrecps.f32 d1, d3, d1
+        vmul.f32   d3, d1, d3
+        vmul.f32   d0, d0, d3
 
+        vst1.32           {d0[0]}, [r0]!
 
-.L_check_float:
-     @ check if anything left to process at the end of the input array
-        cmp               r4, #0
-        ble               .L_return_float
+        bgt               .L_residualloop_float
 
-.L_secondloop_float:
-     @ process the last few items left in the input array
-        vld1.f32          d0[0], [r1]!           @ Fill in d0[0]
-        vld1.f32          d1[0], [r2]!           @ Fill in d1[1]
+.L_check_mainloop_float:
+        cbz               r3, .L_return_float
 
+        @ load the current set of values
+        vld1.32         {q0}, [r1]!
+        vld1.32         {q1}, [r2]!
 
-        subs              r4, r4, #1
+.L_mainloop_float:
+        @ calculate values for the 2nd/next (e.g. 3rd) set
+        vrecpe.f32 q3, q1
+        vrecps.f32 q1, q3, q1
+        vmul.f32   q3, q1, q3
+        vmul.f32   q3, q0, q3
 
-        @ values d0 = d0 / d1
-          vrecpe.f32 d3, d1
-          vrecps.f32 d1, d3, d1
-          vmul.f32   d3, d1, d3
-          vmul.f32   d0, d0, d3
+        @ store the result for the 1st/next (e.g. 3rd) set
+        vst1.32         {d6,d7}, [r0]!
+        subs            r3, r3, #1
 
-        vst1.32           {d0[0]}, [r0]!
+        @ load the next (e.g. 3rd) set of values
+        vld1.32         {q0}, [r1]!
+        vld1.32         {q1}, [r2]!
 
-        bgt               .L_secondloop_float
+        bgt             .L_mainloop_float             @ loop if r3 > 0, if we have at least another 4 floats
 
 .L_return_float:
-     @ return
+        @ return
         pop               {r4}
         mov               r0, #0
         bx                lr
@@ -137,7 +106,7 @@ div_float_neon:
 
 
 
-        .balign   4
+        .align   4
         .global   vdiv_vec2f_neon
         .thumb
         .thumb_func
@@ -156,119 +125,74 @@ vdiv_vec2f_neon:
         @  r3: int count & the number of items in the input array that can be
         @                   processed in chunks of 4 vectors
         @
-        @  r4:  the number of items that are left to be processed at the end of
+        @  r4:  the number of items that are residual that will be processed at the begin of
         @                   the input array
         @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
         push              {r4}
-        and               r4, r3, #3          @ r4 = count % 4;
-        sub               r3, r3, r4          @ count = count - r3; This is what's left to be processed after this loop
-
-        cmp               r3, #0
-        beq               .L_check_vec2
+        and               r4, r3, #3          @ r4 = count % 4; calculate the residual loop
+        asr               r3, r3, #2          @ r3 = count >> 2; calculate the main loop
 
-        @ load the 1st set of values
-          vld2.32         {q0-q1}, [r1]!
-          vld2.32         {q2-q3}, [r2]!
-          subs            r3, r3, #8          @ 4 for this set, and 4 for the 2nd set
-
-        @ calculate values for the 1st set
-        @ q8 = q0 / q2
-          vrecpe.f32 q8, q2
-          vrecps.f32 q2, q8, q2
-          vmul.f32   q8, q2, q8
-          vmul.f32   q8, q0, q8
+        cbz               r4, .L_check_mainloop_vec2
 
-        @ q9 = q1 / q3
-          vrecpe.f32 q9, q3
-          vrecps.f32 q3, q9, q3
-          vmul.f32   q9, q3, q9
-          vmul.f32   q9, q1, q9
-
-        @ load the 2nd set of values
-          vld2.32         {q0-q1}, [r1]!
-          vld2.32         {q2-q3}, [r2]!
-
-          ble             .L_mainloopend_vec2
+.L_residualloop_vec2:
+        @  process the residual items in the input array
+        vld1.f32          d0, [r1]!
+        vld1.f32          d1, [r2]!
 
-.L_mainloop_vec2:
-        @ store the result for the 1st/next (e.g. 3rd) set
-          vst2.32         {d16,d17,d18,d19}, [r0]!
+        subs              r4, r4, #1
 
-        @ calculate values for the 2nd/next (e.g. 3rd) set
-        @ q8 = q0 / q2
-          vrecpe.f32 q8, q2
-          vrecps.f32 q2, q8, q2
-          vmul.f32   q8, q2, q8
-          vmul.f32   q8, q0, q8
+        @ calculate values
+        @ d0 = d0 / d1
+        vrecpe.f32 d4, d1
+        vrecps.f32 d1, d4, d1
+        vmul.f32   d4, d1, d4
+        vmul.f32   d0, d0, d4
 
-        @ q9 = q1 / q3
-          vrecpe.f32 q9, q3
-          vrecps.f32 q3, q9, q3
-          vmul.f32   q9, q3, q9
-          vmul.f32   q9, q1, q9
+        vst1.32           {d0}, [r0]!
 
-       @ load the next (e.g. 3rd) set of values
-          vld2.32         {q0-q1}, [r1]!
-          vld2.32         {q2-q3}, [r2]!
-          subs            r3, r3, #4
+        bgt               .L_residualloop_vec2
 
-        bgt             .L_mainloop_vec2             @ loop if r2 is > r3, if we have at least another 4 vectors (8 floats) to process
+.L_check_mainloop_vec2:
+        cbz               r3, .L_return_vec2
 
-.L_mainloopend_vec2:
-        @ the last iteration for this call
-        @ store the result for the set of values before the last one (e.g 2nd set)
-          vst2.32         {d16,d17,d18,d19}, [r0]!
+        @ load the current set of values
+        vld2.32         {q0-q1}, [r1]!
+        vld2.32         {q2-q3}, [r2]!
 
-        @ calculate values for the last (e.g. 3rd) set
+.L_mainloop_vec2:
+        @ calculate values for current set
         @ q8 = q0 / q2
-          vrecpe.f32 q8, q2
-          vrecps.f32 q2, q8, q2
-          vmul.f32   q8, q2, q8
-          vmul.f32   q8, q0, q8
+        vrecpe.f32 q8, q2
+        vrecps.f32 q2, q8, q2
+        vmul.f32   q8, q2, q8
+        vmul.f32   q8, q0, q8
 
         @ q9 = q1 / q3
-          vrecpe.f32 q9, q3
-          vrecps.f32 q3, q9, q3
-          vmul.f32   q9, q3, q9
-          vmul.f32   q9, q1, q9
+        vrecpe.f32 q9, q3
+        vrecps.f32 q3, q9, q3
+        vmul.f32   q9, q3, q9
+        vmul.f32   q9, q1, q9
 
-        @ store the result for the last (e.g. 3rd) set
-          vst2.32         {d16,d17,d18,d19}, [r0]!
+        @ store the result for current set
+        vst2.32         {d16,d17,d18,d19}, [r0]!
+        subs            r3, r3, #1
 
-.L_check_vec2:
-     @ check if anything left to process at the end of the input array
-        cmp               r4, #0
-        ble               .L_return_vec2
-
-.L_secondloop_vec2:
-     @ process the last few items left in the input array
-        vld1.f32          d0, [r1]!
-        vld1.f32          d1, [r2]!
-
-        subs              r4, r4, #1
-
-        @ calculate values
-        @ d0 = d0 / d1
-          vrecpe.f32 d4, d1
-          vrecps.f32 d1, d4, d1
-          vmul.f32   d4, d1, d4
-          vmul.f32   d0, d0, d4
-
-        vst1.32           {d0}, [r0]!
+        @ load the next set of values
+        vld2.32         {q0-q1}, [r1]!
+        vld2.32         {q2-q3}, [r2]!
 
-        bgt               .L_secondloop_vec2
+        bgt             .L_mainloop_vec2             @ loop if r3 > 0, if we have at least another 4 vectors (8 floats) to process
 
 .L_return_vec2:
-     @ return
+        @ return
         pop               {r4}
         mov               r0, #0
         bx                lr
 
 
 
-
-        .align  2
+        .align  4
         .global vdiv_vec3f_neon
         .thumb
         .thumb_func
@@ -286,120 +210,18 @@ vdiv_vec3f_neon:
         @  r3: int count & the number of items in the input array that can be
         @                   processed in chunks of 4 vectors
         @
-        @  r4:  the number of items that are left to be processed at the end of
+        @  r4:  the number of items that are residual that will be processed at the begin of
         @                   the input array
         @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
         push              {r4}
-        and               r4, r3, #3          @ r3 = count % 4;
-        sub               r3, r3, r4          @ count = count - r3; This is what's left to be processed after this loop
-
-        cmp               r3, #0
-        beq               .L_check_vec3
-
-        @ load the 1st set of values
-          vld3.32         {d0, d2, d4}, [r1]!
-          vld3.32         {d1, d3, d5}, [r1]!
-          vld3.32         {d18, d20, d22}, [r2]!
-          vld3.32         {d19, d21, d23}, [r2]!
-          subs            r3, r3, #8          @ 4 for this set, and 4 for the 2nd set
-
-        @ calculate values for the 1st set
-          @  q12 = q0 / q9
-          vrecpe.f32 q12, q9
-          vrecps.f32 q9 , q12, q9
-          vmul.f32   q12, q9 , q12
-          vmul.f32   q12, q0 , q12
-
-          @  q13 = q1 / q10
-          vrecpe.f32 q13, q10
-          vrecps.f32 q10 , q13, q10
-          vmul.f32   q13, q10 , q13
-          vmul.f32   q13, q1 , q13
-
-          @  q14 = q2 / q11
-          vrecpe.f32 q14, q11
-          vrecps.f32 q11 , q14, q11
-          vmul.f32   q14, q11 , q14
-          vmul.f32   q14, q2 , q14
-
-        @ load the 2nd set of values
-          vld3.32         {d0, d2, d4}, [r1]!
-          vld3.32         {d1, d3, d5}, [r1]!
-          vld3.32         {d18, d20, d22}, [r2]!
-          vld3.32         {d19, d21, d23}, [r2]!
-
-          ble             .L_mainloopend_vec3
+        and               r4, r3, #3          @ r4 = count % 4; calculate the residual loop
+        asr               r3, r3, #2          @ r3 = count >> 2; calculate the main loop
 
-.L_mainloop_vec3:
-        @ store the result for the 1st/next (e.g. 3rd) set
-          vst3.32         {d24, d26, d28}, [r0]!
-          vst3.32         {d25, d27, d29}, [r0]!
+        cbz               r4, .L_check_mainloop_vec3
 
-        @ calculate values for the 2nd/next (e.g. 3rd) set
-          @  q12 = q0 / q9
-          vrecpe.f32 q12, q9
-          vrecps.f32 q9 , q12, q9
-          vmul.f32   q12, q9 , q12
-          vmul.f32   q12, q0 , q12
-
-          @  q13 = q1 / q10
-          vrecpe.f32 q13, q10
-          vrecps.f32 q10 , q13, q10
-          vmul.f32   q13, q10 , q13
-          vmul.f32   q13, q1 , q13
-
-          @  q14 = q2 / q11
-          vrecpe.f32 q14, q11
-          vrecps.f32 q11 , q14, q11
-          vmul.f32   q14, q11 , q14
-          vmul.f32   q14, q2 , q14
-
-       @ load the next (e.g. 3rd) set of values
-          vld3.32         {d0, d2, d4}, [r1]!
-          vld3.32         {d1, d3, d5}, [r1]!
-          vld3.32         {d18, d20, d22}, [r2]!
-          vld3.32         {d19, d21, d23}, [r2]!
-          subs            r3, r3, #4
-
-        bgt               .L_mainloop_vec3             @ loop if r2 is > r3, if we have at least another 4 vectors (12 floats) to process
-
-.L_mainloopend_vec3:
-        @ the last iteration for this call
-        @ store the result for the set of values before the last one (e.g 2nd set)
-          vst3.32         {d24, d26, d28}, [r0]!
-          vst3.32         {d25, d27, d29}, [r0]!
-
-        @ calculate values for the last (e.g. 3rd) set
-          @  q12 = q0 / q9
-          vrecpe.f32 q12, q9
-          vrecps.f32 q9 , q12, q9
-          vmul.f32   q12, q9 , q12
-          vmul.f32   q12, q0 , q12
-
-          @  q13 = q1 / q10
-          vrecpe.f32 q13, q10
-          vrecps.f32 q10 , q13, q10
-          vmul.f32   q13, q10 , q13
-          vmul.f32   q13, q1 , q13
-
-          @  q14 = q2 / q11
-          vrecpe.f32 q14, q11
-          vrecps.f32 q11 , q14, q11
-          vmul.f32   q14, q11 , q14
-          vmul.f32   q14, q2 , q14
-
-        @ store the result for the last (e.g. 3rd) set
-          vst3.32         {d24, d26, d28}, [r0]!
-          vst3.32         {d25, d27, d29}, [r0]!
-
-.L_check_vec3:
-     @ check if anything left to process at the end of the input array
-        cmp               r4, #0
-        ble               .L_return_vec3
-
-.L_secondloop_vec3:
-     @ process the last few items left in the input array
+.L_residualloop_vec3:
+        @  process the residual items in the input array
         vld3.f32          {d0[0], d2[0], d4[0]}, [r1]!     @ The values are loaded like so:
                                                            @      q0 = { V1.x, -, -, - };
                                                            @      q1 = { V1.y, -, -, - };
@@ -412,27 +234,69 @@ vdiv_vec3f_neon:
         subs              r4, r4, #1
 
         @ calculate values for
-          vrecpe.f32 d18, d1
-          vrecps.f32 d1 , d18, d1
-          vmul.f32   d18, d1 , d18
-          vmul.f32   d0 , d0 , d18
+        vrecpe.f32 d18, d1
+        vrecps.f32 d1 , d18, d1
+        vmul.f32   d18, d1 , d18
+        vmul.f32   d0 , d0 , d18
 
-          vrecpe.f32 d20, d3
-          vrecps.f32 d3 , d20, d3
-          vmul.f32   d20, d3 , d20
-          vmul.f32   d2 , d2 , d20
+        vrecpe.f32 d20, d3
+        vrecps.f32 d3 , d20, d3
+        vmul.f32   d20, d3 , d20
+        vmul.f32   d2 , d2 , d20
 
-          vrecpe.f32 d22, d5
-          vrecps.f32 d5 , d22, d5
-          vmul.f32   d22, d5 , d22
-          vmul.f32   d4 , d4 , d22
+        vrecpe.f32 d22, d5
+        vrecps.f32 d5 , d22, d5
+        vmul.f32   d22, d5 , d22
+        vmul.f32   d4 , d4 , d22
 
         vst3.32           {d0[0], d2[0], d4[0]}, [r0]!
 
-        bgt               .L_secondloop_vec3
+        bgt               .L_residualloop_vec3
+
+.L_check_mainloop_vec3:
+        cbz               r3, .L_return_vec3
+
+        @ load current set of values
+        vld3.32         {d0, d2, d4}, [r1]!
+        vld3.32         {d1, d3, d5}, [r1]!
+        vld3.32         {d18, d20, d22}, [r2]!
+        vld3.32         {d19, d21, d23}, [r2]!
+
+.L_mainloop_vec3:
+        @ calculate values for current set
+        @  q12 = q0 / q9
+        vrecpe.f32 q12, q9
+        vrecps.f32 q9 , q12, q9
+        vmul.f32   q12, q9 , q12
+        vmul.f32   q12, q0 , q12
+
+        @  q13 = q1 / q10
+        vrecpe.f32 q13, q10
+        vrecps.f32 q10 , q13, q10
+        vmul.f32   q13, q10 , q13
+        vmul.f32   q13, q1 , q13
+
+        @  q14 = q2 / q11
+        vrecpe.f32 q14, q11
+        vrecps.f32 q11 , q14, q11
+        vmul.f32   q14, q11 , q14
+        vmul.f32   q14, q2 , q14
+
+        @ store the result for current set
+        vst3.32         {d24, d26, d28}, [r0]!
+        vst3.32         {d25, d27, d29}, [r0]!
+        subs            r3, r3, #1
+
+        @ load next set of values
+        vld3.32         {d0, d2, d4}, [r1]!
+        vld3.32         {d1, d3, d5}, [r1]!
+        vld3.32         {d18, d20, d22}, [r2]!
+        vld3.32         {d19, d21, d23}, [r2]!
+
+        bgt               .L_mainloop_vec3             @ loop if r3 > 0, if we have at least another 4 vectors (12 floats) to process
 
 .L_return_vec3:
-     @ return
+        @ return
         pop               {r4}
         mov               r0, #0
         bx                lr
@@ -440,7 +304,7 @@ vdiv_vec3f_neon:
 
 
 
-        .align  2
+        .align  4
         .global vdiv_vec4f_neon
         .thumb
         .thumb_func
@@ -458,183 +322,86 @@ vdiv_vec4f_neon:
         @  r3: int count & the number of items in the input array that can be
         @                   processed in chunks of 4 vectors
         @
-        @  r4:  the number of items that are left to be processed at the end of
+        @  r4:  the number of items that are residual that will be processed at the begin of
         @                   the input array
         @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
         push              {r4}
-        and               r4, r3, #3          @ r4 = count % 4;
-        sub               r3, r3, r4          @ count = count - r4; This is what's left to be processed after this loop
-
-        cmp               r3, #0
-        beq               .L_check_vec4
-
-        @ load the 1st set of values
-          vld4.32         {d0, d2, d4, d6}, [r1]!
-          vld4.32         {d1, d3, d5, d7}, [r1]!
-          vld4.32         {d16, d18, d20, d22}, [r2]!
-          vld4.32         {d17, d19, d21, d23}, [r2]!
-
-          subs            r3, r3, #8           @ 4 for this set, and 4 for the 2nd set
-
-        @ calculate values for the 1st set
-          @  q12 = q0 / q8
-          vrecpe.f32 q12, q8
-          vrecps.f32 q8 , q12, q8
-          vmul.f32   q12, q8 , q12
-          vmul.f32   q12, q0 , q12
-
-          @  q13 = q1 / q9
-          vrecpe.f32 q13, q9
-          vrecps.f32 q9 , q13, q9
-          vmul.f32   q13, q9 , q13
-          vmul.f32   q13, q1 , q13
-
-          @  q14 = q2 / q10
-          vrecpe.f32 q14, q10
-          vrecps.f32 q10 , q14, q10
-          vmul.f32   q14, q10 , q14
-          vmul.f32   q14, q2 , q14
-
-          @  q15 = q3 / q11
-          vrecpe.f32 q15, q11
-          vrecps.f32 q11 , q15, q11
-          vmul.f32   q15, q11 , q15
-          vmul.f32   q15, q3 , q15
-
-        @ load the 2nd set of values
-          vld4.32         {d0, d2, d4, d6}, [r1]!
-          vld4.32         {d1, d3, d5, d7}, [r1]!
-          vld4.32         {d16, d18, d20, d22}, [r2]!
-          vld4.32         {d17, d19, d21, d23}, [r2]!
-
-          ble             .L_mainloopend_vec4
+        and               r4, r3, #3          @ r4 = count % 4; calculate the residual loop
+        asr               r3, r3, #2          @ r3 = count >> 2; calculate the main loop
 
-.L_mainloop_vec4:
-        @ store the result for the 1st/next (e.g. 3rd) set
-          vst4.32         {d24, d26, d28, d30}, [r0]!
-          vst4.32         {d25, d27, d29, d31}, [r0]!
+        cbz               r4, .L_check_mainloop_vec4
 
-        @ calculate values for the 2nd/next (e.g. 3rd) set
-          @  q12 = q0 / q8
-          vrecpe.f32 q12, q8
-          vrecps.f32 q8 , q12, q8
-          vmul.f32   q12, q8 , q12
-          vmul.f32   q12, q0 , q12
-
-          @  q13 = q1 / q9
-          vrecpe.f32 q13, q9
-          vrecps.f32 q9 , q13, q9
-          vmul.f32   q13, q9 , q13
-          vmul.f32   q13, q1 , q13
-
-          @  q14 = q2 / q10
-          vrecpe.f32 q14, q10
-          vrecps.f32 q10 , q14, q10
-          vmul.f32   q14, q10 , q14
-          vmul.f32   q14, q2 , q14
-
-          @  q15 = q3 / q11
-          vrecpe.f32 q15, q11
-          vrecps.f32 q11 , q15, q11
-          vmul.f32   q15, q11 , q15
-          vmul.f32   q15, q3 , q15
-
-       @ load the next (e.g. 3rd) set of values
-          vld4.32         {d0, d2, d4, d6}, [r1]!
-          vld4.32         {d1, d3, d5, d7}, [r1]!
-          vld4.32         {d16, d18, d20, d22}, [r2]!
-          vld4.32         {d17, d19, d21, d23}, [r2]!
-          subs            r3, r3, #4
-
-        bgt               .L_mainloop_vec4             @ loop if r2 is > r3, if we have at least another 4 vectors (16 floats) to process
-
-.L_mainloopend_vec4:
-        @ the last iteration for this call
-        @ store the result for the set of values before the last one (e.g 2nd set)
-          vst4.32         {d24, d26, d28, d30}, [r0]!
-          vst4.32         {d25, d27, d29, d31}, [r0]!
-
-        @ calculate values for the last (e.g. 3rd) set
-          @  q12 = q0 / q8
-          vrecpe.f32 q12, q8
-          vrecps.f32 q8 , q12, q8
-          vmul.f32   q12, q8 , q12
-          vmul.f32   q12, q0 , q12
-
-          @  q13 = q1 / q9
-          vrecpe.f32 q13, q9
-          vrecps.f32 q9 , q13, q9
-          vmul.f32   q13, q9 , q13
-          vmul.f32   q13, q1 , q13
-
-          @  q14 = q2 / q10
-          vrecpe.f32 q14, q10
-          vrecps.f32 q10 , q14, q10
-          vmul.f32   q14, q10 , q14
-          vmul.f32   q14, q2 , q14
-
-          @  q15 = q3 / q11
-          vrecpe.f32 q15, q11
-          vrecps.f32 q11 , q15, q11
-          vmul.f32   q15, q11 , q15
-          vmul.f32   q15, q3 , q15
-
-        @ store the result for the last (e.g. 3rd) set
-          vst4.32         {d24, d26, d28, d30}, [r0]!
-          vst4.32         {d25, d27, d29, d31}, [r0]!
-
-.L_check_vec4:
-     @ check if anything left to process at the end of the input array
-        cmp               r4, #0
-        ble               .L_return_vec4
-
-.L_secondloop_vec4:
-     @ process the last few items left in the input array
-        vld4.f32          {d0[0], d2[0], d4[0], d6[0]}, [r1]!     @ The values are loaded like so:
-                                                                  @      q0 = { V1.x, -, -, - };
-                                                                  @      q1 = { V1.y, -, -, - };
-                                                                  @      q2 = { V1.z, -, -, - };
-                                                                  @      q3 = { V1.w, -, -, - };
-        vld4.f32          {d1[0], d3[0], d5[0], d7[0]}, [r2]!     @ The values are loaded like so:
-                                                                  @      q0 = { V1.x, -, V2.x, - };
-                                                                  @      q1 = { V1.y, -, V2.y, - };
-                                                                  @      q2 = { V1.z, -, V2.z, - };
-                                                                  @      q3 = { V1.w, -, V2.w, - };
+.L_residualloop_vec4:
+        @ process the last few items left in the input array
+        vld1.f32          {d0, d1}, [r1]!     @ The values are loaded like so:
+                                                                  @      q0 = { V1.x, V1.y, V1.z, V1.w };
+        vld1.f32          {d2, d3}, [r2]!     @ The values are loaded like so:
+                                                                  @      q1 = { V2.x, V2.y, V2.z, V2.w };
 
         subs              r4, r4, #1
 
         @ calculate values
-          @  d0 = d0 / d1
-          vrecpe.f32 d18, d1
-          vrecps.f32 d1 , d18, d1
-          vmul.f32   d18, d1 , d18
-          vmul.f32   d0 , d0 , d18
-
-          @  d2 = d2 / d3
-          vrecpe.f32 d20, d3
-          vrecps.f32 d3 , d20, d3
-          vmul.f32   d20, d3 , d20
-          vmul.f32   d2 , d2 , d20
-
-          @  d4 = d4 / d5
-          vrecpe.f32 d22, d5
-          vrecps.f32 d5 , d22, d5
-          vmul.f32   d22, d5 , d22
-          vmul.f32   d4 , d4 , d22
-
-          @  d6 = d6 / d7
-          vrecpe.f32 d16, d7
-          vrecps.f32 d7 , d16, d7
-          vmul.f32   d16, d7 , d16
-          vmul.f32   d6 , d6 , d16
-
-        vst4.32          {d0[0], d2[0], d4[0], d6[0]}, [r0]!
-
-        bgt               .L_secondloop_vec4
+        @  q0 = q0 / q1
+        vrecpe.f32 q2, q1
+        vrecps.f32 q1 , q2, q1
+        vmul.f32   q2, q1 , q2
+        vmul.f32   q0 , q0 , q2
+
+        vst1.32          {d0, d1}, [r0]!
+
+        bgt               .L_residualloop_vec4
+
+.L_check_mainloop_vec4:
+        cbz               r3, .L_return_vec4
+
+        @ load the current set of values
+        vld4.32         {d0, d2, d4, d6}, [r1]!
+        vld4.32         {d1, d3, d5, d7}, [r1]!
+        vld4.32         {d16, d18, d20, d22}, [r2]!
+        vld4.32         {d17, d19, d21, d23}, [r2]!
+
+.L_mainloop_vec4:
+        @ calculate values for current set
+        @  q12 = q0 / q8
+        vrecpe.f32 q12, q8
+        vrecps.f32 q8 , q12, q8
+        vmul.f32   q12, q8 , q12
+        vmul.f32   q12, q0 , q12
+
+        @  q13 = q1 / q9
+        vrecpe.f32 q13, q9
+        vrecps.f32 q9 , q13, q9
+        vmul.f32   q13, q9 , q13
+        vmul.f32   q13, q1 , q13
+
+        @  q14 = q2 / q10
+        vrecpe.f32 q14, q10
+        vrecps.f32 q10 , q14, q10
+        vmul.f32   q14, q10 , q14
+        vmul.f32   q14, q2 , q14
+
+        @  q15 = q3 / q11
+        vrecpe.f32 q15, q11
+        vrecps.f32 q11 , q15, q11
+        vmul.f32   q15, q11 , q15
+        vmul.f32   q15, q3 , q15
+
+        @ store the result for current set
+        vst4.32         {d24, d26, d28, d30}, [r0]!
+        vst4.32         {d25, d27, d29, d31}, [r0]!
+        subs            r3, r3, #1
+
+        @ load the next set of values
+        vld4.32         {d0, d2, d4, d6}, [r1]!
+        vld4.32         {d1, d3, d5, d7}, [r1]!
+        vld4.32         {d16, d18, d20, d22}, [r2]!
+        vld4.32         {d17, d19, d21, d23}, [r2]!
+
+        bgt               .L_mainloop_vec4             @ loop if r3 > 0, if we have at least another 4 vectors (16 floats) to process
 
 .L_return_vec4:
-     @ return
+        @ return
         pop               {r4}
         mov               r0, #0
         bx                lr