aboutsummaryrefslogtreecommitdiffstats
path: root/Transceiver52M/arch/arm/convolve_neon.S
diff options
context:
space:
mode:
Diffstat (limited to 'Transceiver52M/arch/arm/convolve_neon.S')
-rw-r--r--Transceiver52M/arch/arm/convolve_neon.S277
1 files changed, 277 insertions, 0 deletions
diff --git a/Transceiver52M/arch/arm/convolve_neon.S b/Transceiver52M/arch/arm/convolve_neon.S
new file mode 100644
index 0000000..637d150
--- /dev/null
+++ b/Transceiver52M/arch/arm/convolve_neon.S
@@ -0,0 +1,277 @@
+/*
+ * NEON Convolution
+ * Copyright (C) 2012, 2013 Thomas Tsou <tom@tsou.cc>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+ .syntax unified
+ .text
+ .align 2
+ .global neon_conv_real4
+ .type neon_conv_real4, %function
+neon_conv_real4:
+ push {r4, lr}
+ vpush {q4-q7}
+ vld2.32 {q0-q1}, [r1]
+ ldr r4, =8
+.neon_conv_loop4:
+ vld2.32 {q2-q3}, [r0], r4
+ vmul.f32 q4, q2, q0
+ vmul.f32 q5, q3, q0
+ vpadd.f32 d12, d8, d9
+ vpadd.f32 d13, d10, d11
+ vpadd.f32 d14, d12, d13
+ vst1.64 {d14}, [r2]!
+ subs r3, r3, #1
+ bne .neon_conv_loop4
+ vpop {q4-q7}
+ pop {r4, pc}
+ .size neon_conv_real4, .-neon_conv_real4
+ .align 2
+ .p2align 4,,15
+ .global neon_conv_real8
+ .type neon_conv_real8, %function
+neon_conv_real8:
+ push {r4-r5, lr}
+ vpush {q4-q7}
+ vld2.32 {q0-q1}, [r1]!
+ vld2.32 {q2-q3}, [r1]
+ add r4, r0, #32
+ ldr r5, =8
+.neon_conv_loop8:
+ vld2.32 {q4-q5}, [r0], r5
+ vld2.32 {q6-q7}, [r4], r5
+ vmul.f32 q8, q4, q0
+ vmul.f32 q9, q5, q0
+ vmul.f32 q10, q6, q2
+ vmul.f32 q11, q7, q2
+
+ vadd.f32 q12, q8, q10
+ vadd.f32 q13, q9, q11
+
+ vpadd.f32 d22, d24, d25
+ vpadd.f32 d23, d26, d27
+ vpadd.f32 d24, d22, d23
+ vst1.64 {d24}, [r2]!
+ subs r3, r3, #1
+ bne .neon_conv_loop8
+ vpop {q4-q7}
+ pop {r4-r5, pc}
+ .size neon_conv_real8, .-neon_conv_real8
+ .align 2
+ .global neon_conv_real12
+ .type neon_conv_real12, %function
+neon_conv_real12:
+ push {r4-r6, lr}
+ vpush {q4-q7}
+ vld2.32 {q0-q1}, [r1]!
+ vld2.32 {q2-q3}, [r1]!
+ vld2.32 {q4-q5}, [r1]!
+ add r4, r0, #32
+ add r5, r0, #64
+ ldr r6, =8
+.neon_conv_loop12:
+ vld2.32 {q6-q7}, [r0], r6
+ vld2.32 {q8-q9}, [r4], r6
+ vld2.32 {q10-q11}, [r5], r6
+#ifdef HAVE_NEON_FMA
+ vfma.f32 q1, q6, q0
+ vfma.f32 q3, q7, q0
+ vfma.f32 q1, q8, q2
+ vfma.f32 q3, q9, q2
+ vfma.f32 q1, q10, q4
+ vfma.f32 q3, q11, q4
+#else
+ vmul.f32 q12, q6, q0
+ vmul.f32 q13, q7, q0
+ vmul.f32 q14, q8, q2
+ vmul.f32 q15, q9, q2
+ vmul.f32 q1, q10, q4
+ vmul.f32 q3, q11, q4
+
+ vadd.f32 q5, q12, q14
+ vadd.f32 q6, q13, q15
+ vadd.f32 q1, q5, q1
+ vadd.f32 q3, q6, q3
+#endif
+ vpadd.f32 d2, d2, d3
+ vpadd.f32 d3, d6, d7
+ vpadd.f32 d6, d2, d3
+ vst1.64 {d6}, [r2]!
+ subs r3, r3, #1
+ bne .neon_conv_loop12
+ vpop {q4-q7}
+ pop {r4-r6, pc}
+ .size neon_conv_real12, .-neon_conv_real12
+ .align 2
+ .global neon_conv_real16
+ .type neon_conv_real16, %function
+neon_conv_real16:
+ push {r4-r7, lr}
+ vpush {q4-q7}
+ vld2.32 {q0-q1}, [r1]!
+ vld2.32 {q2-q3}, [r1]!
+ vld2.32 {q4-q5}, [r1]!
+ vld2.32 {q6-q7}, [r1]
+ add r4, r0, #32
+ add r5, r0, #64
+ add r6, r0, #96
+ ldr r7, =8
+.neon_conv_loop16:
+ vld2.32 {q8-q9}, [r0], r7
+ vld2.32 {q10-q11}, [r4], r7
+ vld2.32 {q12-q13}, [r5], r7
+ vld2.32 {q14-q15}, [r6], r7
+#ifdef HAVE_NEON_FMA
+ vmul.f32 q1, q8, q0
+ vmul.f32 q3, q9, q0
+ vfma.f32 q1, q10, q2
+ vfma.f32 q3, q11, q2
+ vfma.f32 q1, q12, q4
+ vfma.f32 q3, q13, q4
+ vfma.f32 q1, q14, q6
+ vfma.f32 q3, q15, q6
+#else
+ vmul.f32 q1, q8, q0
+ vmul.f32 q3, q9, q0
+ vmul.f32 q5, q10, q2
+ vmul.f32 q7, q11, q2
+ vmul.f32 q8, q12, q4
+ vmul.f32 q9, q13, q4
+ vmul.f32 q10, q14, q6
+ vmul.f32 q11, q15, q6
+
+ vadd.f32 q1, q1, q5
+ vadd.f32 q3, q3, q7
+ vadd.f32 q5, q8, q10
+ vadd.f32 q7, q9, q11
+ vadd.f32 q1, q1, q5
+ vadd.f32 q3, q3, q7
+#endif
+ vpadd.f32 d2, d2, d3
+ vpadd.f32 d3, d6, d7
+ vpadd.f32 d6, d2, d3
+ vst1.64 {d6}, [r2]!
+ subs r3, r3, #1
+ bne .neon_conv_loop16
+ vpop {q4-q7}
+ pop {r4-r7, pc}
+ .size neon_conv_real16, .-neon_conv_real16
+ .align 2
+ .global neon_conv_real20
+ .type neon_conv_real20, %function
+neon_conv_real20:
+ push {r4-r8, lr}
+ vpush {q4-q7}
+ vld2.32 {q0-q1}, [r1]!
+ vld2.32 {q2-q3}, [r1]!
+ vld2.32 {q4-q5}, [r1]!
+ vld2.32 {q6-q7}, [r1]!
+ vld2.32 {q8-q9}, [r1]
+ add r4, r0, #32
+ add r5, r0, #64
+ add r6, r0, #96
+ add r7, r0, #128
+ ldr r8, =8
+.neon_conv_loop20:
+ vld2.32 {q10-q11}, [r0], r8
+ vld2.32 {q12-q13}, [r4], r8
+ vld2.32 {q14-q15}, [r5], r8
+#ifdef HAVE_NEON_FMA
+ vmul.f32 q1, q10, q0
+ vfma.f32 q1, q12, q2
+ vfma.f32 q1, q14, q4
+ vmul.f32 q3, q11, q0
+ vfma.f32 q3, q13, q2
+ vfma.f32 q3, q15, q4
+
+ vld2.32 {q12-q13}, [r6], r8
+ vld2.32 {q14-q15}, [r7], r8
+
+ vfma.f32 q1, q12, q6
+ vfma.f32 q3, q13, q6
+ vfma.f32 q1, q14, q8
+ vfma.f32 q3, q15, q8
+#else
+ vmul.f32 q1, q10, q0
+ vmul.f32 q3, q12, q2
+ vmul.f32 q5, q14, q4
+ vmul.f32 q7, q11, q0
+ vmul.f32 q9, q13, q2
+ vmul.f32 q10, q15, q4
+ vadd.f32 q1, q1, q3
+ vadd.f32 q3, q7, q9
+ vadd.f32 q9, q1, q5
+ vadd.f32 q10, q3, q10
+
+ vld2.32 {q12-q13}, [r6], r8
+ vld2.32 {q14-q15}, [r7], r8
+
+ vmul.f32 q1, q12, q6
+ vmul.f32 q3, q13, q6
+ vmul.f32 q5, q14, q8
+ vmul.f32 q7, q15, q8
+ vadd.f32 q12, q1, q9
+ vadd.f32 q14, q3, q10
+ vadd.f32 q1, q12, q5
+ vadd.f32 q3, q14, q7
+#endif
+ vpadd.f32 d2, d2, d3
+ vpadd.f32 d3, d6, d7
+ vpadd.f32 d6, d2, d3
+ vst1.64 {d6}, [r2]!
+ subs r3, r3, #1
+ bne .neon_conv_loop20
+ vpop {q4-q7}
+ pop {r4-r8, pc}
+ .size neon_conv_real20, .-neon_conv_real20
+ .align 2
+ .global mac_cx_neon4
+ .type mac_cx_neon4, %function
+mac_cx_neon4:
+ push {r4, lr}
+ ldr r4, =32
+ veor q14, q14
+ veor q15, q15
+.neon_conv_loop_mac4:
+ vld2.32 {q0-q1}, [r0], r4
+ vld2.32 {q2-q3}, [r1]!
+
+ vmul.f32 q10, q0, q2
+ vmul.f32 q11, q1, q3
+ vmul.f32 q12, q0, q3
+ vmul.f32 q13, q2, q1
+ vsub.f32 q8, q10, q11
+ vadd.f32 q9, q12, q13
+
+ vadd.f32 q14, q8
+ vadd.f32 q15, q9
+ subs r3, #1
+ bne .neon_conv_loop_mac4
+
+ vld1.64 d0, [r2]
+ vpadd.f32 d28, d28, d29
+ vpadd.f32 d30, d30, d31
+ vpadd.f32 d1, d28, d30
+ vadd.f32 d1, d0
+ vst1.64 d1, [r2]
+ pop {r4, pc}
+ .size mac_cx_neon4, .-mac_cx_neon4
+ .section .note.GNU-stack,"",%progbits